WP Broken Link Status Checker - Version 1.0.5

Version Description

March 7th, 2019

  • Tested with PHP 7.0 and PHP 7.2
  • Tested with WP 5.x and Gutenberg
  • Coding style corrections
  • Fixed several soft bugs
  • Allow activation/deactivation/uninstall without admin area restriction
  • Prevent network-wide plugin activation for multisite installs
  • Remove threads with off status to avoid TEXT field overflow
  • More time to HTTP CURL spawn method to run
  • Improvements in debug and trace mode
Download this release

Release Info

Developer seedplugins
Plugin Icon 128x128 WP Broken Link Status Checker
Version 1.0.5
Comparing to
See all releases

Code changes from version 1.0.4 to 1.0.5

admin/admin.php CHANGED
@@ -1,13 +1,13 @@
1
  <?php
2
 
3
  // Load dependencies
4
- require_once(dirname(dirname(__FILE__)).'/core/module.php');
5
 
6
  /**
7
- * WP Link Status Admin class
8
  *
9
  * @package WP Link Status
10
- * @subpackage WP Link Status Admin
11
  */
12
  class WPLNST_Admin extends WPLNST_Core_Module {
13
 
@@ -50,40 +50,40 @@ class WPLNST_Admin extends WPLNST_Core_Module {
50
  * Custom constructor
51
  */
52
  protected function on_construct($args = null) {
53
-
54
  // Dependencies
55
  wplnst_require('core', 'text');
56
-
57
  // Load translations
58
  add_action('plugins_loaded', array('WPLNST_Core_Plugin', 'load_plugin_textdomain'));
59
-
60
  // Check AJAX Mode
61
  if (defined('DOING_AJAX') && DOING_AJAX) {
62
-
63
  // Check this plugin action
64
  if (!empty($_POST['action']) && 0 === strpos($_POST['action'], 'wplnst_')) {
65
-
66
  // Check suffix
67
  $suffix = mb_substr($_POST['action'], 7);
68
  if (!empty($suffix) && method_exists($this, 'ajax_'.$suffix)) {
69
-
70
  // Set AJAX handler
71
  add_action('wp_ajax_'.$_POST['action'], array(&$this, 'ajax_'.$suffix));
72
  }
73
  }
74
-
75
  // Continue
76
  } else {
77
-
78
  // Check submit
79
  $this->scans_edit_submit_check();
80
-
81
  // Menu
82
  add_action('admin_menu', array(&$this, 'admin_menu'));
83
-
84
  // Enqueues
85
  add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueue'));
86
-
87
  // Screen options
88
  add_filter('set-screen-option', array(&$this, 'options_screen_set'), 11, 3);
89
  }
@@ -95,30 +95,32 @@ class WPLNST_Admin extends WPLNST_Core_Module {
95
  * Enqueue scripts and styles
96
  */
97
  public function admin_enqueue() {
98
-
99
  // Check plugin context
100
- if (!self::is_plugin_page())
101
  return;
102
-
 
103
  // Compose script version
104
  $this->script_version = self::get_script_version();
105
-
106
  // Commmon admin styles
107
  wp_enqueue_style('wplnst-admin-css', plugins_url('assets/css/admin.css', WPLNST_FILE), array(), $this->script_version);
108
-
109
  // jQuery Lightboxed plugin
110
  wp_enqueue_script('wplnst-admin-lighboxed', plugins_url('assets/js/lightboxed/jquery.lightboxed.min.js', WPLNST_FILE), array('jquery'), $this->script_version, true);
111
-
112
  // Common admin script
113
  wp_enqueue_script('wplnst-admin-script', plugins_url('assets/js/admin.js', WPLNST_FILE), array('jquery'), $this->script_version, true);
114
-
115
  // Edit scan script
116
- if (WPLNST_Core_Plugin::slug.'-new-scan' == $_GET['page'] || (!empty($_GET['context']) && 'edit' == $_GET['context']))
117
  wp_enqueue_script('wplnst-admin-script-edit', plugins_url('assets/js/admin-edit.js', WPLNST_FILE), array('jquery', 'json2'), $this->script_version, true);
118
-
 
119
  // Enqueue version specific scripts
120
  $this->admin_enqueue_version();
121
-
122
  // Screen options
123
  $this->options_screen_add();
124
  }
@@ -138,23 +140,23 @@ class WPLNST_Admin extends WPLNST_Core_Module {
138
  * Admin menu hooks
139
  */
140
  public function admin_menu() {
141
-
142
  // Base 64 encoded SVG image
143
- $icon_svg = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiICAgdmVyc2lvbj0iMS4xIiAgIHg9IjBweCIgICB5PSIwcHgiICAgdmlld0JveD0iMCAwIDEwMCAxMDAiICAgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTAwIDEwMCIgICB4bWw6c3BhY2U9InByZXNlcnZlIiAgIGlkPSJzdmcyIiAgIGlua3NjYXBlOnZlcnNpb249IjAuNDguNCByOTkzOSIgICB3aWR0aD0iMTAwJSIgICBoZWlnaHQ9IjEwMCUiICAgc29kaXBvZGk6ZG9jbmFtZT0ibGluay1zdGF0dXMtNy5zdmciPjxtZXRhZGF0YSAgICAgaWQ9Im1ldGFkYXRhMTAiPjxyZGY6UkRGPjxjYzpXb3JrICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcyAgICAgaWQ9ImRlZnM4IiAvPjxzb2RpcG9kaTpuYW1lZHZpZXcgICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIgICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IiAgICAgYm9yZGVyb3BhY2l0eT0iMSIgICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiICAgICBncmlkdG9sZXJhbmNlPSIxMCIgICAgIGd1aWRldG9sZXJhbmNlPSIxMCIgICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIgICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTY4MCIgICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9Ijk3NCIgICAgIGlkPSJuYW1lZHZpZXc2IiAgICAgc2hvd2dyaWQ9ImZhbHNlIiAgICAgaW5rc2NhcGU6em9vbT0iMi4zNiIgICAgIGlua3NjYXBlOmN4PSItMjguNjAxNjk1IiAgICAgaW5rc2NhcGU6Y3k9IjUwIiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjAiICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMjQiICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ic3ZnMiIgLz48cGF0aCAgICAgZD0iTTUwLDBDMjIuNCwwLDAsMjIuNCwwLDUwczIyLjQsNTAsNTAsNTBzNTAtMjIuNCw1MC01MFM3Ny42LDAsNTAsMHogTTU1LjgsNjUuM0w0NCw3N2MtMy4yLDMuMi03LjUsNS0xMS44LDVoMCAgYy0zLjksMC03LjUtMS41LTEwLjItNC4xYy01LjgtNS44LTUuOC0xNS4zLDAtMjEuMWwxNC4xLTE0LjFMMzYsNDQuOWMtMC4yLDIuNiwwLjEsNS4xLDAuOSw3LjRsMC4yLDAuNWwtOS41LDkuNSAgYy0xLjQsMS40LTIuMSwzLjItMi4xLDUuMWMwLDEuOSwwLjcsMy43LDIuMSw1LjFjMS4yLDEuMiwyLjksMS45LDQuNywxLjljMi4zLDAsNC42LTEsNi4zLTIuN2wxMS43LTExLjdjMy4zLTMuMywzLjctOC4yLDAuOS0xMSAgYy0wLjctMC43LTEtMS45LTAuOC0zLjFjMC4yLTEuMiwwLjgtMi4zLDEuNy0zLjJsMS41LTEuNWwwLjUsMC4zYzAuOSwwLjYsMS44LDEuMywyLjUsMmMwLjgsMC44LDEuNCwxLjYsMiwyLjYgIEM2Mi4zLDUxLjksNjEuMSw2MCw1NS44LDY1LjN6IE03Ny45LDQzLjJMNjMuOCw1Ny4zbDAuMi0yLjFjMC4yLTIuNi0wLjEtNS4xLTAuOS03LjRMNjMsNDcuMmw5LjUtOS41YzEuNC0xLjQsMi4xLTMuMiwyLjEtNS4xICBjMC0xLjktMC43LTMuNy0yLjEtNS4xYy0xLjItMS4yLTIuOS0xLjktNC43LTEuOWMtMi4zLDAtNC42LDEtNi4zLDIuN0w0OS43LDQwLjFjLTMuMywzLjMtMy43LDguMi0wLjksMTFjMC43LDAuNywxLDEuOSwwLjgsMy4xICBjLTAuMiwxLjItMC44LDIuMy0xLjcsMy4yTDQ2LjQsNTlsLTAuNS0wLjNjLTAuOS0wLjYtMS44LTEuMy0yLjUtMmMtMC44LTAuOC0xLjQtMS42LTItMi42Yy0zLjYtNS45LTIuNC0xNC4xLDIuOS0xOS40TDU2LDIzICBjMy4yLTMuMiw3LjUtNSwxMS44LTVjMy45LDAsNy41LDEuNSwxMC4yLDQuMWMyLjgsMi44LDQuNCw2LjYsNC40LDEwLjVDODIuMywzNi42LDgwLjcsNDAuNCw3Ny45LDQzLjJ6IiAgICAgaWQ9InBhdGg0IiAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZjtmaWxsLW9wYWNpdHk6MSIgLz48L3N2Zz4=';
144
-
145
  // Main menu
146
  add_menu_page($this->get_plugin_title(), $this->get_menu_title(), WPLNST_Core_Plugin::capability, WPLNST_Core_Plugin::slug, array(&$this, 'admin_menu_scans'), $icon_svg, '99.20226');
147
-
148
  // Scans
149
  add_submenu_page(WPLNST_Core_Plugin::slug, self::get_text('scans'), self::get_text('scans'), WPLNST_Core_Plugin::capability, WPLNST_Core_Plugin::slug, array(&$this, 'admin_menu_scans'));
150
  add_submenu_page(WPLNST_Core_Plugin::slug, self::get_text('scan_new'), self::get_text('scan_new'), WPLNST_Core_Plugin::capability, WPLNST_Core_Plugin::slug.'-new-scan', array(&$this, 'admin_menu_scans_new'));
151
-
152
  // Utilities
153
  $this->admin_menu_utilities();
154
-
155
  // Settings
156
  add_submenu_page(WPLNST_Core_Plugin::slug, self::get_text('settings'), self::get_text('settings'), WPLNST_Core_Plugin::capability, WPLNST_Core_Plugin::slug.'-settings', array(&$this, 'admin_menu_settings'));
157
-
158
  // Addons
159
  $this->admin_menu_addons();
160
  }
@@ -232,17 +234,19 @@ class WPLNST_Admin extends WPLNST_Core_Module {
232
  * Check a submit attempt
233
  */
234
  private function scans_edit_submit_check() {
235
-
236
  // Check plugin context
237
- if (!self::is_plugin_page())
238
  return;
239
-
 
240
  // Edit scan form, early check because maybe do a redirection for new scans
241
  if ((WPLNST_Core_Plugin::slug == $_GET['page'] && !empty($_GET['context']) && 'edit' == $_GET['context']) || WPLNST_Core_Plugin::slug.'-new-scan' == $_GET['page']) {
242
-
243
  // Check id and nonce submit
244
- if (isset($_POST['scan_id']) && isset($_POST['scan_edit_nonce']))
245
  add_action('admin_init', array(&$this, 'scans_edit_submit'));
 
246
  }
247
  }
248
 
@@ -268,16 +272,16 @@ class WPLNST_Admin extends WPLNST_Core_Module {
268
  * Add options to the admin screen
269
  */
270
  private function options_screen_add() {
271
-
272
  // Check scans context
273
  if (WPLNST_Core_Plugin::slug == $_GET['page']) {
274
-
275
  // Scans list
276
  if (!isset($_GET['scan_id']) && empty($_GET['context'])) {
277
  $option_default = WPLNST_Core_Types::scans_per_page;
278
  $option_per_page = 'wplnst_scans_per_page';
279
  $option_label = __('Scans per page', 'wplnst');
280
-
281
  // Results list
282
  } elseif (isset($_GET['context']) && 'results' == $_GET['context']) {
283
  $option_default = WPLNST_Core_Types::scans_results_per_page;
@@ -285,7 +289,7 @@ class WPLNST_Admin extends WPLNST_Core_Module {
285
  $option_label = __('Crawler results per page', 'wplnst');
286
  }
287
  }
288
-
289
  // Check option result
290
  if (isset($option_label)) {
291
  add_screen_option('per_page', array(
@@ -302,7 +306,7 @@ class WPLNST_Admin extends WPLNST_Core_Module {
302
  * Set the screen options
303
  */
304
  public function options_screen_set($status, $option, $value) {
305
-
306
  // Options names
307
  $allowed = array(
308
  'scans_per_page',
@@ -311,8 +315,9 @@ class WPLNST_Admin extends WPLNST_Core_Module {
311
 
312
  // Enum allowed
313
  foreach ($allowed as $name) {
314
- if ('wplnst_'.$name == $option)
315
  return $value;
 
316
  }
317
  }
318
 
@@ -327,13 +332,13 @@ class WPLNST_Admin extends WPLNST_Core_Module {
327
  * Show default admin view
328
  */
329
  public function screen_view($args) {
330
-
331
  // Set plugin title
332
  $args['plugin_title'] = $this->get_plugin_title();
333
-
334
  // Before the screen output
335
  $this->screen_view_before();
336
-
337
  // And show it
338
  self::screen_view_output($args);
339
  }
@@ -353,26 +358,26 @@ class WPLNST_Admin extends WPLNST_Core_Module {
353
  * Output the screen view
354
  */
355
  private static function screen_view_output($args) {
356
-
357
  // Vars
358
  extract($args);
359
-
360
  ?><div class="wrap wplnst-wrap">
361
-
362
  <h2 id="wplnst-title"><?php echo empty($title)? '' : $title.' - '; echo $plugin_title; if (!empty($add_item_text) && !empty($add_item_url)) : ?> <a class="add-new-h2" href="<?php echo esc_url($add_item_url); ?>"><?php echo esc_html($add_item_text); ?></a><?php endif; ?></h2>
363
-
364
- <?php if (!wplnst_is_curl_enabled()) : ?><div class="error notice"><p><?php _e('Not detected the required cURL module enabled. Please contact with your hosting provider in order to install cURL for PHP in this server.', 'wplnst'); ?></p></div><?php endif; ?>
365
-
366
  <?php if (!empty($notice_error)) : ?><div class="error notice"><p><?php echo $notice_error; ?></p></div><?php endif; ?>
367
-
368
  <?php if (!empty($notice_success)) : ?><div class="updated notice is-dismissible"><p><?php echo $notice_success; ?></p></div><?php endif; ?>
369
-
370
  <?php if (!empty($notice_warning)) : ?><div class="notice notice-warning is-dismissible"><p><?php echo $notice_warning; ?></p></div><?php endif; ?>
371
-
372
  <?php if (!empty($notice_crawler)) : ?><div class="updated notice is-dismissible"><p><?php echo $notice_crawler; ?></p></div><?php endif; ?>
373
-
374
  <?php if (!empty($wp_action)) do_action($wp_action, $args); ?>
375
-
376
  </div><?php
377
  }
378
 
1
  <?php
2
 
3
  // Load dependencies
4
+ require_once dirname(dirname(__FILE__)).'/core/module.php';
5
 
6
  /**
7
+ * Admin class
8
  *
9
  * @package WP Link Status
10
+ * @subpackage Admin
11
  */
12
  class WPLNST_Admin extends WPLNST_Core_Module {
13
 
50
  * Custom constructor
51
  */
52
  protected function on_construct($args = null) {
53
+
54
  // Dependencies
55
  wplnst_require('core', 'text');
56
+
57
  // Load translations
58
  add_action('plugins_loaded', array('WPLNST_Core_Plugin', 'load_plugin_textdomain'));
59
+
60
  // Check AJAX Mode
61
  if (defined('DOING_AJAX') && DOING_AJAX) {
62
+
63
  // Check this plugin action
64
  if (!empty($_POST['action']) && 0 === strpos($_POST['action'], 'wplnst_')) {
65
+
66
  // Check suffix
67
  $suffix = mb_substr($_POST['action'], 7);
68
  if (!empty($suffix) && method_exists($this, 'ajax_'.$suffix)) {
69
+
70
  // Set AJAX handler
71
  add_action('wp_ajax_'.$_POST['action'], array(&$this, 'ajax_'.$suffix));
72
  }
73
  }
74
+
75
  // Continue
76
  } else {
77
+
78
  // Check submit
79
  $this->scans_edit_submit_check();
80
+
81
  // Menu
82
  add_action('admin_menu', array(&$this, 'admin_menu'));
83
+
84
  // Enqueues
85
  add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueue'));
86
+
87
  // Screen options
88
  add_filter('set-screen-option', array(&$this, 'options_screen_set'), 11, 3);
89
  }
95
  * Enqueue scripts and styles
96
  */
97
  public function admin_enqueue() {
98
+
99
  // Check plugin context
100
+ if (!self::is_plugin_page()) {
101
  return;
102
+ }
103
+
104
  // Compose script version
105
  $this->script_version = self::get_script_version();
106
+
107
  // Commmon admin styles
108
  wp_enqueue_style('wplnst-admin-css', plugins_url('assets/css/admin.css', WPLNST_FILE), array(), $this->script_version);
109
+
110
  // jQuery Lightboxed plugin
111
  wp_enqueue_script('wplnst-admin-lighboxed', plugins_url('assets/js/lightboxed/jquery.lightboxed.min.js', WPLNST_FILE), array('jquery'), $this->script_version, true);
112
+
113
  // Common admin script
114
  wp_enqueue_script('wplnst-admin-script', plugins_url('assets/js/admin.js', WPLNST_FILE), array('jquery'), $this->script_version, true);
115
+
116
  // Edit scan script
117
+ if (WPLNST_Core_Plugin::slug.'-new-scan' == $_GET['page'] || (!empty($_GET['context']) && 'edit' == $_GET['context'])) {
118
  wp_enqueue_script('wplnst-admin-script-edit', plugins_url('assets/js/admin-edit.js', WPLNST_FILE), array('jquery', 'json2'), $this->script_version, true);
119
+ }
120
+
121
  // Enqueue version specific scripts
122
  $this->admin_enqueue_version();
123
+
124
  // Screen options
125
  $this->options_screen_add();
126
  }
140
  * Admin menu hooks
141
  */
142
  public function admin_menu() {
143
+
144
  // Base 64 encoded SVG image
145
+ $icon_svg = @include WPLNST_PATH.'/assets/icon.php';
146
+
147
  // Main menu
148
  add_menu_page($this->get_plugin_title(), $this->get_menu_title(), WPLNST_Core_Plugin::capability, WPLNST_Core_Plugin::slug, array(&$this, 'admin_menu_scans'), $icon_svg, '99.20226');
149
+
150
  // Scans
151
  add_submenu_page(WPLNST_Core_Plugin::slug, self::get_text('scans'), self::get_text('scans'), WPLNST_Core_Plugin::capability, WPLNST_Core_Plugin::slug, array(&$this, 'admin_menu_scans'));
152
  add_submenu_page(WPLNST_Core_Plugin::slug, self::get_text('scan_new'), self::get_text('scan_new'), WPLNST_Core_Plugin::capability, WPLNST_Core_Plugin::slug.'-new-scan', array(&$this, 'admin_menu_scans_new'));
153
+
154
  // Utilities
155
  $this->admin_menu_utilities();
156
+
157
  // Settings
158
  add_submenu_page(WPLNST_Core_Plugin::slug, self::get_text('settings'), self::get_text('settings'), WPLNST_Core_Plugin::capability, WPLNST_Core_Plugin::slug.'-settings', array(&$this, 'admin_menu_settings'));
159
+
160
  // Addons
161
  $this->admin_menu_addons();
162
  }
234
  * Check a submit attempt
235
  */
236
  private function scans_edit_submit_check() {
237
+
238
  // Check plugin context
239
+ if (!self::is_plugin_page()) {
240
  return;
241
+ }
242
+
243
  // Edit scan form, early check because maybe do a redirection for new scans
244
  if ((WPLNST_Core_Plugin::slug == $_GET['page'] && !empty($_GET['context']) && 'edit' == $_GET['context']) || WPLNST_Core_Plugin::slug.'-new-scan' == $_GET['page']) {
245
+
246
  // Check id and nonce submit
247
+ if (isset($_POST['scan_id']) && isset($_POST['scan_edit_nonce'])) {
248
  add_action('admin_init', array(&$this, 'scans_edit_submit'));
249
+ }
250
  }
251
  }
252
 
272
  * Add options to the admin screen
273
  */
274
  private function options_screen_add() {
275
+
276
  // Check scans context
277
  if (WPLNST_Core_Plugin::slug == $_GET['page']) {
278
+
279
  // Scans list
280
  if (!isset($_GET['scan_id']) && empty($_GET['context'])) {
281
  $option_default = WPLNST_Core_Types::scans_per_page;
282
  $option_per_page = 'wplnst_scans_per_page';
283
  $option_label = __('Scans per page', 'wplnst');
284
+
285
  // Results list
286
  } elseif (isset($_GET['context']) && 'results' == $_GET['context']) {
287
  $option_default = WPLNST_Core_Types::scans_results_per_page;
289
  $option_label = __('Crawler results per page', 'wplnst');
290
  }
291
  }
292
+
293
  // Check option result
294
  if (isset($option_label)) {
295
  add_screen_option('per_page', array(
306
  * Set the screen options
307
  */
308
  public function options_screen_set($status, $option, $value) {
309
+
310
  // Options names
311
  $allowed = array(
312
  'scans_per_page',
315
 
316
  // Enum allowed
317
  foreach ($allowed as $name) {
318
+ if ('wplnst_'.$name == $option) {
319
  return $value;
320
+ }
321
  }
322
  }
323
 
332
  * Show default admin view
333
  */
334
  public function screen_view($args) {
335
+
336
  // Set plugin title
337
  $args['plugin_title'] = $this->get_plugin_title();
338
+
339
  // Before the screen output
340
  $this->screen_view_before();
341
+
342
  // And show it
343
  self::screen_view_output($args);
344
  }
358
  * Output the screen view
359
  */
360
  private static function screen_view_output($args) {
361
+
362
  // Vars
363
  extract($args);
364
+
365
  ?><div class="wrap wplnst-wrap">
366
+
367
  <h2 id="wplnst-title"><?php echo empty($title)? '' : $title.' - '; echo $plugin_title; if (!empty($add_item_text) && !empty($add_item_url)) : ?> <a class="add-new-h2" href="<?php echo esc_url($add_item_url); ?>"><?php echo esc_html($add_item_text); ?></a><?php endif; ?></h2>
368
+
369
+ <?php if (!wplnst_is_curl_enabled()) : ?><div class="error notice"><p><?php _e('Not detected the required cURL module enabled. Please contact with your hosting provider in order to install cURL for PHP on this server.', 'wplnst'); ?></p></div><?php endif; ?>
370
+
371
  <?php if (!empty($notice_error)) : ?><div class="error notice"><p><?php echo $notice_error; ?></p></div><?php endif; ?>
372
+
373
  <?php if (!empty($notice_success)) : ?><div class="updated notice is-dismissible"><p><?php echo $notice_success; ?></p></div><?php endif; ?>
374
+
375
  <?php if (!empty($notice_warning)) : ?><div class="notice notice-warning is-dismissible"><p><?php echo $notice_warning; ?></p></div><?php endif; ?>
376
+
377
  <?php if (!empty($notice_crawler)) : ?><div class="updated notice is-dismissible"><p><?php echo $notice_crawler; ?></p></div><?php endif; ?>
378
+
379
  <?php if (!empty($wp_action)) do_action($wp_action, $args); ?>
380
+
381
  </div><?php
382
  }
383
 
admin/extensions.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Admin Extensions class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Admin
8
  */
9
  class WPLNST_Admin_Extensions {
10
 
@@ -14,10 +14,10 @@ class WPLNST_Admin_Extensions {
14
  * Constructor
15
  */
16
  public function __construct(&$admin) {
17
-
18
  // Custom action view
19
  add_action('wplnst_view_extensions', array(&$this, 'view_extensions'));
20
-
21
  // Show settings screen
22
  $admin->screen_view(array(
23
  'title' => __('Extensions', 'wplnst'),
1
  <?php
2
 
3
  /**
4
+ * Admin Extensions class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Admin
8
  */
9
  class WPLNST_Admin_Extensions {
10
 
14
  * Constructor
15
  */
16
  public function __construct(&$admin) {
17
+
18
  // Custom action view
19
  add_action('wplnst_view_extensions', array(&$this, 'view_extensions'));
20
+
21
  // Show settings screen
22
  $admin->screen_view(array(
23
  'title' => __('Extensions', 'wplnst'),
admin/scans-submit.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Admin Scans Submit class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Admin
8
  */
9
  class WPLNST_Admin_Scans_Submit {
10
 
@@ -24,35 +24,35 @@ class WPLNST_Admin_Scans_Submit {
24
  * Handle submit in the constructor
25
  */
26
  public function __construct($scans) {
27
-
28
  // Globals
29
  global $wpdb;
30
-
31
  // Check scan identifier
32
  $scan_id = isset($_POST['scan_id'])? (int) $_POST['scan_id'] : false;
33
  if (false === $scan_id || (isset($_GET['scan_id']) && $scan_id != (int) $_GET['scan_id'])) {
34
  $this->notice_error = WPLNST_Admin::get_text('invalid_data');
35
  return;
36
  }
37
-
38
  // Check existing scan
39
  if ($scan_id > 0 && false === ($scan = $scans->get_scan_by_id($scan_id))) {
40
  $this->notice_error = WPLNST_Admin::get_text('scan_not_found');
41
  return;
42
  }
43
-
44
  // Check submitted nonce
45
  $nonce = isset($_POST['scan_edit_nonce'])? $_POST['scan_edit_nonce'] : false;
46
  if (false === $nonce || !wp_verify_nonce($nonce, 'scan-edit-'.(empty($scan)? '0' : $scan->hash))) {
47
  $this->notice_error = WPLNST_Admin::get_text('invalid_nonce');
48
  return;
49
  }
50
-
51
  // Collect data
52
  $max_threads = isset($_POST['tx-threads'])? (int) $_POST['tx-threads'] : 0;
53
  $connect_timeout = isset($_POST['tx-connect-timeout'])? (int) $_POST['tx-connect-timeout'] : 0;
54
  $request_timeout = isset($_POST['tx-request-timeout'])? (int) $_POST['tx-request-timeout'] : 0;
55
-
56
  // Update data array
57
  $updates = array(
58
  'modified_by' => get_current_user_id(),
@@ -62,36 +62,37 @@ class WPLNST_Admin_Scans_Submit {
62
  'connect_timeout' => $connect_timeout,
63
  'request_timeout' => $request_timeout,
64
  );
65
-
66
-
67
  // Initialize
68
  $config = array();
69
-
70
-
71
  /* Notifications */
72
-
73
  // Empty of not completed
74
  if (empty($scan) || 'end' != $scan->status) {
75
-
76
  // Check config for existing scan
77
  if (!empty($scan) && 'wait' != $scan->status) {
78
  $config = @json_decode($scan->row->config, true);
79
- if (empty($config) || !is_array($config))
80
  $config = array();
 
81
  }
82
-
83
  // Set e-mail settings
84
  $config['notify_default'] = WPLNST_Core_Types::check_post_value('ck-notify-default', 'on', false);
85
  $config['notify_address'] = WPLNST_Core_Types::check_post_value('ck-notify-address', 'on', false);
86
  $config['notify_address_email'] = isset($_POST['tx-notify-address-email'])? substr(trim(stripslashes($_POST['tx-notify-address-email'])), 0, 255) : '';
87
  }
88
-
89
-
90
  /* Editable scan */
91
-
92
  // Editable fields
93
  if (empty($scan) || 'wait' == $scan->status) {
94
-
95
  // General tab
96
  $config['destination_type'] = WPLNST_Core_Types::check_post_value('sl-destination-type', array_keys(WPLNST_Core_Types::get_destination_types()), 'all');
97
  $config['time_scope'] = WPLNST_Core_Types::check_post_value('sl-time-scope', array_keys(WPLNST_Core_Types::get_time_scopes()), 'anytime');
@@ -99,17 +100,17 @@ class WPLNST_Admin_Scans_Submit {
99
  $config['crawl_order'] = WPLNST_Core_Types::check_post_value('sl-crawl-order', array_keys(WPLNST_Core_Types::get_crawl_order()), 'asc');
100
  $config['redir_status'] = WPLNST_Core_Types::check_post_value('ck-redir-status', 'on', false);
101
  $config['malformed'] = WPLNST_Core_Types::check_post_value('ck-malformed-links', 'on', false);
102
-
103
  // Content options tab
104
  $config['post_types'] = WPLNST_Core_Types::check_post_value('ck-post-type', array_keys(WPLNST_Core_Types::get_post_types()), array());
105
  $config['post_status'] = WPLNST_Core_Types::check_post_value('ck-post-status', array_keys(WPLNST_Core_Types::get_post_status()), array());
106
  $config['comment_types'] = WPLNST_Core_Types::check_post_value('ck-comment-type', array_keys(WPLNST_Core_Types::get_comment_types()), array());
107
  $config['blogroll'] = WPLNST_Core_Types::check_post_value('ck-blogroll', 'on', false);
108
-
109
  // Links status tab
110
  $config['status_levels'] = WPLNST_Core_Types::check_post_value('ck-status-level', array_keys(WPLNST_Core_Types::get_status_levels()), array());
111
  $config['status_codes'] = WPLNST_Core_Types::check_post_value('ck-status-code', array_keys(WPLNST_Core_Types::get_status_codes_raw()), array());
112
-
113
  // Filters
114
  $config['custom_fields'] = WPLNST_Core_Types::check_post_elist('scan_custom_fields');
115
  $config['anchor_filters'] = WPLNST_Core_Types::check_post_elist('scan_anchor_filters');
@@ -118,159 +119,161 @@ class WPLNST_Admin_Scans_Submit {
118
  $config['html_attributes'] = WPLNST_Core_Types::check_post_elist('scan_html_attributes');
119
  $config['filtered_query'] = WPLNST_Core_Types::check_post_value('ck-filtered-query', 'on', false);
120
  }
121
-
122
  // Add to update
123
- if (!empty($config))
124
  $updates['config'] = @json_encode($config);
125
-
126
-
 
127
  /* Save and run */
128
-
129
  // Check run attempt
130
  $do_play = (isset($_POST['scan_run']) && 1 == (int) $_POST['scan_run']);
131
-
132
  // Abort when cURL is not enabled
133
- if ($do_play && !wplnst_is_curl_enabled())
134
  $do_play = false;
135
-
 
136
  // Check new scan
137
  if (empty($scan_id)) {
138
-
139
  // Create unique random hash associated with the scan
140
  $hash = md5(rand(0, 9999).microtime().rand(0, 9999));
141
-
142
  // Add scan and redirect
143
  $wpdb->insert($wpdb->prefix.'wplnst_scans', array_merge($updates, array('status' => 'wait', 'hash' => $hash, 'created_at' => current_time('mysql', true))));
144
-
145
  // New identifier
146
  $insert_id = (int) $wpdb->insert_id;
147
-
148
  // Check error
149
  if (empty($insert_id)) {
150
-
151
  // Message error
152
  $this->notice_error = __('Something went wrong adding the new scan. Please <a href="javascript:history.back();">go back</a> and attempt again to submit form.');
153
-
154
  // Scan added
155
  } else {
156
-
157
  // Run scan
158
  if ($do_play) {
159
-
160
  // Check max scans running
161
  if (!$scans->can_play_more_scans()) {
162
-
163
  // Maximum reached
164
  $started = 'max_scans';
165
-
166
  // Queue scan
167
  $scans->queue_scan($insert_id);
168
-
169
  // Retrieve scan
170
  } elseif (false === ($scan = $scans->get_scan_by_id($insert_id))) {
171
-
172
  // Can`t start scan
173
  $started = 'error';
174
-
175
  // Check ready
176
  } elseif (true === $scans->is_scan_ready($scan)) {
177
-
178
  // Update scan ready
179
  $scans->update_scan_ready($scan->id, true);
180
-
181
  // Attempt to run scan
182
  if (false === $scans->play_scan($scan->id)) {
183
-
184
  // Can`t start scan
185
  $started = 'error';
186
-
187
  // Running
188
  } else {
189
-
190
  // Done
191
  $started = 'on';
192
-
193
  // Save default threads values
194
  $scans->set_scan_final_threads_options($scan->id, array(
195
  'max_threads' => $max_threads,
196
  'connect_timeout' => $connect_timeout,
197
  'request_timeout' => $request_timeout,
198
  ));
199
-
200
  // Attemp to run scan
201
  WPLNST_Core_Alive::run($scan->id, $hash);
202
  }
203
  }
204
  }
205
-
206
  // Redirect to scan edit permalink
207
  wp_redirect(WPLNST_Core_Plugin::get_url_scans_edit($insert_id, true, $do_play? $started : false));
208
-
209
  // End
210
  die;
211
  }
212
-
213
  // Update scan
214
  } else {
215
-
216
  // Update threads values if scan is in play mode
217
  if ('play' == $scan->status) {
218
  $updates['max_threads'] = wplnst_get_nsetting('max_threads', $max_threads);
219
  $updates['connect_timeout'] = wplnst_get_nsetting('connect_timeout', $connect_timeout);
220
  $updates['request_timeout'] = wplnst_get_nsetting('request_timeout', $request_timeout);
221
  }
222
-
223
  // Update scan data
224
  $rows = $wpdb->update($wpdb->prefix.'wplnst_scans', $updates, array('scan_id' => $scan->id));
225
  if (empty($rows) || false === ($scan = $scans->get_scan_by_id($scan->id))) {
226
-
227
  // Message error
228
  $this->notice_error = __('Something went wrong updating the scan data. Please <a href="javascript:history.back();">go back</a> and attempt again to save data.', 'wplnst');
229
-
230
  // Done
231
  } else {
232
-
233
  // Update message
234
  $this->notice_success = __('Scan updated successfully.', 'wplnst');
235
-
236
  // Check if run the crawler, only for waiting scans
237
  if ($do_play && 'wait' == $scan->status) {
238
-
239
  // Check max scans running
240
  if (!$scans->can_play_more_scans()) {
241
-
242
  // Maximum reached
243
  $this->notice_warning = WPLNST_Admin::get_text('max_scans');
244
-
245
  // Queue scan
246
  $scans->queue_scan($scan->id);
247
-
248
  // Set to play
249
  } elseif (false === $scans->play_scan($scan->id)) {
250
-
251
  // Crawler not started
252
  $this->notice_warning = sprintf(__('Something went wrong trying to start the crawler.'));
253
-
254
  // Done
255
  } else {
256
-
257
  // Save default threads values
258
  $scans->set_scan_final_threads_options($scan->id, array(
259
  'max_threads' => $max_threads,
260
  'connect_timeout' => $connect_timeout,
261
  'request_timeout' => $request_timeout,
262
  ));
263
-
264
  // Run scan
265
  WPLNST_Core_Alive::run($scan->id, $scan->hash);
266
-
267
  // Update message
268
  $this->notice_crawler = sprintf(__('The crawler for this scan is running. You can see its data in the <a href="%s">crawler results page</a>.', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan->id)));
269
  }
270
-
271
  // Not play
272
  } elseif ('wait' == $scan->status && $scans->can_play_more_scans() && true === $scans->is_scan_ready($scan)) {
273
-
274
  // Start crawler reminder
275
  $start_url = esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($scan->id, 'on', $scan->hash));
276
  $this->notice_success .= ' '.sprintf(__('The crawler for this scan is <strong>not started</strong>, you can <a href="%s">start the crawler</a> now.', 'wplnst'), $start_url);
1
  <?php
2
 
3
  /**
4
+ * Admin Scans Submit class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Admin
8
  */
9
  class WPLNST_Admin_Scans_Submit {
10
 
24
  * Handle submit in the constructor
25
  */
26
  public function __construct($scans) {
27
+
28
  // Globals
29
  global $wpdb;
30
+
31
  // Check scan identifier
32
  $scan_id = isset($_POST['scan_id'])? (int) $_POST['scan_id'] : false;
33
  if (false === $scan_id || (isset($_GET['scan_id']) && $scan_id != (int) $_GET['scan_id'])) {
34
  $this->notice_error = WPLNST_Admin::get_text('invalid_data');
35
  return;
36
  }
37
+
38
  // Check existing scan
39
  if ($scan_id > 0 && false === ($scan = $scans->get_scan_by_id($scan_id))) {
40
  $this->notice_error = WPLNST_Admin::get_text('scan_not_found');
41
  return;
42
  }
43
+
44
  // Check submitted nonce
45
  $nonce = isset($_POST['scan_edit_nonce'])? $_POST['scan_edit_nonce'] : false;
46
  if (false === $nonce || !wp_verify_nonce($nonce, 'scan-edit-'.(empty($scan)? '0' : $scan->hash))) {
47
  $this->notice_error = WPLNST_Admin::get_text('invalid_nonce');
48
  return;
49
  }
50
+
51
  // Collect data
52
  $max_threads = isset($_POST['tx-threads'])? (int) $_POST['tx-threads'] : 0;
53
  $connect_timeout = isset($_POST['tx-connect-timeout'])? (int) $_POST['tx-connect-timeout'] : 0;
54
  $request_timeout = isset($_POST['tx-request-timeout'])? (int) $_POST['tx-request-timeout'] : 0;
55
+
56
  // Update data array
57
  $updates = array(
58
  'modified_by' => get_current_user_id(),
62
  'connect_timeout' => $connect_timeout,
63
  'request_timeout' => $request_timeout,
64
  );
65
+
66
+
67
  // Initialize
68
  $config = array();
69
+
70
+
71
  /* Notifications */
72
+
73
  // Empty of not completed
74
  if (empty($scan) || 'end' != $scan->status) {
75
+
76
  // Check config for existing scan
77
  if (!empty($scan) && 'wait' != $scan->status) {
78
  $config = @json_decode($scan->row->config, true);
79
+ if (empty($config) || !is_array($config)) {
80
  $config = array();
81
+ }
82
  }
83
+
84
  // Set e-mail settings
85
  $config['notify_default'] = WPLNST_Core_Types::check_post_value('ck-notify-default', 'on', false);
86
  $config['notify_address'] = WPLNST_Core_Types::check_post_value('ck-notify-address', 'on', false);
87
  $config['notify_address_email'] = isset($_POST['tx-notify-address-email'])? substr(trim(stripslashes($_POST['tx-notify-address-email'])), 0, 255) : '';
88
  }
89
+
90
+
91
  /* Editable scan */
92
+
93
  // Editable fields
94
  if (empty($scan) || 'wait' == $scan->status) {
95
+
96
  // General tab
97
  $config['destination_type'] = WPLNST_Core_Types::check_post_value('sl-destination-type', array_keys(WPLNST_Core_Types::get_destination_types()), 'all');
98
  $config['time_scope'] = WPLNST_Core_Types::check_post_value('sl-time-scope', array_keys(WPLNST_Core_Types::get_time_scopes()), 'anytime');
100
  $config['crawl_order'] = WPLNST_Core_Types::check_post_value('sl-crawl-order', array_keys(WPLNST_Core_Types::get_crawl_order()), 'asc');
101
  $config['redir_status'] = WPLNST_Core_Types::check_post_value('ck-redir-status', 'on', false);
102
  $config['malformed'] = WPLNST_Core_Types::check_post_value('ck-malformed-links', 'on', false);
103
+
104
  // Content options tab
105
  $config['post_types'] = WPLNST_Core_Types::check_post_value('ck-post-type', array_keys(WPLNST_Core_Types::get_post_types()), array());
106
  $config['post_status'] = WPLNST_Core_Types::check_post_value('ck-post-status', array_keys(WPLNST_Core_Types::get_post_status()), array());
107
  $config['comment_types'] = WPLNST_Core_Types::check_post_value('ck-comment-type', array_keys(WPLNST_Core_Types::get_comment_types()), array());
108
  $config['blogroll'] = WPLNST_Core_Types::check_post_value('ck-blogroll', 'on', false);
109
+
110
  // Links status tab
111
  $config['status_levels'] = WPLNST_Core_Types::check_post_value('ck-status-level', array_keys(WPLNST_Core_Types::get_status_levels()), array());
112
  $config['status_codes'] = WPLNST_Core_Types::check_post_value('ck-status-code', array_keys(WPLNST_Core_Types::get_status_codes_raw()), array());
113
+
114
  // Filters
115
  $config['custom_fields'] = WPLNST_Core_Types::check_post_elist('scan_custom_fields');
116
  $config['anchor_filters'] = WPLNST_Core_Types::check_post_elist('scan_anchor_filters');
119
  $config['html_attributes'] = WPLNST_Core_Types::check_post_elist('scan_html_attributes');
120
  $config['filtered_query'] = WPLNST_Core_Types::check_post_value('ck-filtered-query', 'on', false);
121
  }
122
+
123
  // Add to update
124
+ if (!empty($config)) {
125
  $updates['config'] = @json_encode($config);
126
+ }
127
+
128
+
129
  /* Save and run */
130
+
131
  // Check run attempt
132
  $do_play = (isset($_POST['scan_run']) && 1 == (int) $_POST['scan_run']);
133
+
134
  // Abort when cURL is not enabled
135
+ if ($do_play && !wplnst_is_curl_enabled()) {
136
  $do_play = false;
137
+ }
138
+
139
  // Check new scan
140
  if (empty($scan_id)) {
141
+
142
  // Create unique random hash associated with the scan
143
  $hash = md5(rand(0, 9999).microtime().rand(0, 9999));
144
+
145
  // Add scan and redirect
146
  $wpdb->insert($wpdb->prefix.'wplnst_scans', array_merge($updates, array('status' => 'wait', 'hash' => $hash, 'created_at' => current_time('mysql', true))));
147
+
148
  // New identifier
149
  $insert_id = (int) $wpdb->insert_id;
150
+
151
  // Check error
152
  if (empty($insert_id)) {
153
+
154
  // Message error
155
  $this->notice_error = __('Something went wrong adding the new scan. Please <a href="javascript:history.back();">go back</a> and attempt again to submit form.');
156
+
157
  // Scan added
158
  } else {
159
+
160
  // Run scan
161
  if ($do_play) {
162
+
163
  // Check max scans running
164
  if (!$scans->can_play_more_scans()) {
165
+
166
  // Maximum reached
167
  $started = 'max_scans';
168
+
169
  // Queue scan
170
  $scans->queue_scan($insert_id);
171
+
172
  // Retrieve scan
173
  } elseif (false === ($scan = $scans->get_scan_by_id($insert_id))) {
174
+
175
  // Can`t start scan
176
  $started = 'error';
177
+
178
  // Check ready
179
  } elseif (true === $scans->is_scan_ready($scan)) {
180
+
181
  // Update scan ready
182
  $scans->update_scan_ready($scan->id, true);
183
+
184
  // Attempt to run scan
185
  if (false === $scans->play_scan($scan->id)) {
186
+
187
  // Can`t start scan
188
  $started = 'error';
189
+
190
  // Running
191
  } else {
192
+
193
  // Done
194
  $started = 'on';
195
+
196
  // Save default threads values
197
  $scans->set_scan_final_threads_options($scan->id, array(
198
  'max_threads' => $max_threads,
199
  'connect_timeout' => $connect_timeout,
200
  'request_timeout' => $request_timeout,
201
  ));
202
+
203
  // Attemp to run scan
204
  WPLNST_Core_Alive::run($scan->id, $hash);
205
  }
206
  }
207
  }
208
+
209
  // Redirect to scan edit permalink
210
  wp_redirect(WPLNST_Core_Plugin::get_url_scans_edit($insert_id, true, $do_play? $started : false));
211
+
212
  // End
213
  die;
214
  }
215
+
216
  // Update scan
217
  } else {
218
+
219
  // Update threads values if scan is in play mode
220
  if ('play' == $scan->status) {
221
  $updates['max_threads'] = wplnst_get_nsetting('max_threads', $max_threads);
222
  $updates['connect_timeout'] = wplnst_get_nsetting('connect_timeout', $connect_timeout);
223
  $updates['request_timeout'] = wplnst_get_nsetting('request_timeout', $request_timeout);
224
  }
225
+
226
  // Update scan data
227
  $rows = $wpdb->update($wpdb->prefix.'wplnst_scans', $updates, array('scan_id' => $scan->id));
228
  if (empty($rows) || false === ($scan = $scans->get_scan_by_id($scan->id))) {
229
+
230
  // Message error
231
  $this->notice_error = __('Something went wrong updating the scan data. Please <a href="javascript:history.back();">go back</a> and attempt again to save data.', 'wplnst');
232
+
233
  // Done
234
  } else {
235
+
236
  // Update message
237
  $this->notice_success = __('Scan updated successfully.', 'wplnst');
238
+
239
  // Check if run the crawler, only for waiting scans
240
  if ($do_play && 'wait' == $scan->status) {
241
+
242
  // Check max scans running
243
  if (!$scans->can_play_more_scans()) {
244
+
245
  // Maximum reached
246
  $this->notice_warning = WPLNST_Admin::get_text('max_scans');
247
+
248
  // Queue scan
249
  $scans->queue_scan($scan->id);
250
+
251
  // Set to play
252
  } elseif (false === $scans->play_scan($scan->id)) {
253
+
254
  // Crawler not started
255
  $this->notice_warning = sprintf(__('Something went wrong trying to start the crawler.'));
256
+
257
  // Done
258
  } else {
259
+
260
  // Save default threads values
261
  $scans->set_scan_final_threads_options($scan->id, array(
262
  'max_threads' => $max_threads,
263
  'connect_timeout' => $connect_timeout,
264
  'request_timeout' => $request_timeout,
265
  ));
266
+
267
  // Run scan
268
  WPLNST_Core_Alive::run($scan->id, $scan->hash);
269
+
270
  // Update message
271
  $this->notice_crawler = sprintf(__('The crawler for this scan is running. You can see its data in the <a href="%s">crawler results page</a>.', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan->id)));
272
  }
273
+
274
  // Not play
275
  } elseif ('wait' == $scan->status && $scans->can_play_more_scans() && true === $scans->is_scan_ready($scan)) {
276
+
277
  // Start crawler reminder
278
  $start_url = esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($scan->id, 'on', $scan->hash));
279
  $this->notice_success .= ' '.sprintf(__('The crawler for this scan is <strong>not started</strong>, you can <a href="%s">start the crawler</a> now.', 'wplnst'), $start_url);
admin/scans.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Admin Scans class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Admin
8
  */
9
  class WPLNST_Admin_Scans {
10
 
@@ -31,14 +31,14 @@ class WPLNST_Admin_Scans {
31
  * Constructor
32
  */
33
  public function __construct(&$admin, $menu) {
34
-
35
  // Copy parent
36
  $this->admin = &$admin;
37
-
38
  // Scans menu
39
  if ('context' == $menu) {
40
  $this->scans_context();
41
-
42
  // Check edit scan menu
43
  } elseif ('edit' == $menu) {
44
  $this->scans_edit();
@@ -51,40 +51,40 @@ class WPLNST_Admin_Scans {
51
  * Scans menu
52
  */
53
  private function scans_context() {
54
-
55
  // Check context
56
  $context = empty($_GET['context'])? false : $_GET['context'];
57
-
58
  // Check scan id parameter
59
  $scan_id = empty($_GET['scan_id'])? 0 : (int) $_GET['scan_id'];
60
-
61
  // Results context
62
  if ('results' == $context) {
63
-
64
  // Crawl results
65
  $this->scans_results($scan_id);
66
-
67
  // Crawling order
68
  } elseif ('crawler' == $context) {
69
-
70
  // Crawl check
71
  $this->scans_crawler($scan_id);
72
-
73
  // Delete context
74
  } elseif ('delete' == $context) {
75
-
76
  // Delete confirm
77
  $this->scans_delete($scan_id);
78
-
79
  // Edit
80
  } elseif ('edit' == $context) {
81
-
82
  // Show edit view
83
  $this->scans_edit($scan_id);
84
-
85
  // Default
86
  } else {
87
-
88
  // List of scans
89
  $this->scans_list();
90
  }
@@ -101,20 +101,20 @@ class WPLNST_Admin_Scans {
101
  * Prepare the list of scans
102
  */
103
  private function scans_list() {
104
-
105
  // Retrieve scans
106
  $scans = $this->admin->get_scans(array(
107
  'setup_names' => true,
108
  'order_by' => 'FIELD(status, "play", "wait", "queued", "stop", "end"), started_at DESC, enqueued_at ASC, created_at DESC',
109
  'paged' => empty($_GET['paged'])? 0 : (int) $_GET['paged'],
110
  ));
111
-
112
  // No isolated mode
113
  $scans->isolated = false;
114
-
115
  // Custom action view
116
  add_action('wplnst_scans_list_view', array(&$this, 'scans_list_view'));
117
-
118
  // Show admin screen
119
  $this->admin->screen_view(array(
120
  'scans' => $scans,
@@ -130,10 +130,10 @@ class WPLNST_Admin_Scans {
130
  * Extension view to display the scans list
131
  */
132
  public function scans_list_view($args) {
133
-
134
  // Dependencies
135
  wplnst_require('views', 'scans');
136
-
137
  // Display table
138
  $list = new WPLNST_Views_Scans($args['scans']);
139
  $list->prepare_items();
@@ -151,29 +151,31 @@ class WPLNST_Admin_Scans {
151
  * Prepare and display crawling results
152
  */
153
  private function scans_results($scan_id) {
154
-
155
  // Atempt to load scan
156
- if (false === ($scan = $this->admin->get_scan_by_id($scan_id, true)))
157
  return $this->admin->screen_scan_not_found(WPLNST_Admin::get_text('crawler_results'));
158
-
 
159
  // Prepare scans data
160
  $scans = (object) array(
161
  'isolated' => true,
162
  'rows' => array($scan),
163
  );
164
-
165
  // Check status param
166
  $status_code = $status_level = false;
167
  $status_test = isset($_GET['status'])? $_GET['status'] : false;
168
  if (false !== $status_test) {
169
  if (1 == strlen($status_test)) {
170
- if ('0' == $status_test || in_array($status_test, $scan->status_levels))
171
  $status_level = $status_test;
 
172
  } elseif (3 == strlen($status_test)) {
173
  $status_code = $status_test;
174
  }
175
  }
176
-
177
  // Check object type param
178
  $object_post_type = false;
179
  $object_type = isset($_GET['otype'])? $_GET['otype'] : false;
@@ -181,73 +183,84 @@ class WPLNST_Admin_Scans {
181
  if (!in_array($object_type, array_keys(WPLNST_Core_Types::get_objects_types()))) {
182
  if (0 === strpos($object_type, 'posts_') && strlen($object_type) > 6) {
183
  $object_post_type_test = mb_substr($object_type, 6);
184
- if (in_array($object_post_type_test, $scan->post_types))
185
  $object_post_type = $object_post_type_test;
 
186
  }
187
  $object_type = false;
188
  }
189
  }
190
-
191
  // Check link type param
192
  $link_type = isset($_GET['ltype'])? $_GET['ltype'] : false;
193
- if (false !== $link_type && !in_array($link_type, array_keys(WPLNST_Core_Types::get_link_types())))
194
  $link_type = false;
 
195
 
196
  // Check ignored or not
197
  $ignored_type = isset($_GET['ig'])? $_GET['ig'] : false;
198
- if (false !== $ignored_type && !in_array($ignored_type, array_keys(WPLNST_Core_Types::get_ignored_types())))
199
  $ignored_type = false;
200
-
 
201
  // Check SEO links
202
  $seo_link_type = isset($_GET['slt'])? $_GET['slt'] : false;
203
- if (false !== $seo_link_type && !in_array($seo_link_type, array_keys(WPLNST_Core_Types::get_seo_link_types())))
204
  $seo_link_type = false;
205
-
 
206
  // Check protocol
207
  $protocol_type = isset($_GET['pt'])? $_GET['pt'] : false;
208
- if (false !== $protocol_type && !in_array($protocol_type, array_keys(WPLNST_Core_Types::get_protocol_types())))
209
  $protocol_type = false;
210
-
 
211
  // Check special
212
  $special_type = isset($_GET['sp'])? $_GET['sp'] : false;
213
- if (false !== $special_type && !in_array($special_type, array_keys(WPLNST_Core_Types::get_special_types())))
214
  $special_type = false;
215
-
 
216
  // Check action
217
  $action_type = isset($_GET['ac'])? $_GET['ac'] : false;
218
- if (false !== $action_type && !in_array($action_type, array_keys(WPLNST_Core_Types::get_action_types())))
219
  $action_type = false;
220
-
 
221
  // Check destination
222
  $dest_type = isset($_GET['dtype'])? $_GET['dtype'] : false;
223
- if (false !== $dest_type && !in_array($dest_type, array_keys(WPLNST_Core_Types::get_destination_types())))
224
  $dest_type = false;
225
-
 
226
  // Check order
227
  $order_type = isset($_GET['or'])? $_GET['or'] : false;
228
- if (false !== $order_type && !in_array($order_type, array_keys(WPLNST_Core_Types::get_crawl_order())) && !in_array($order_type, array_keys(WPLNST_Core_Types::get_order_types())))
229
  $order_type = false;
230
-
 
231
  // Check search URL
232
  $search_url = $search_url_type = false;
233
  $search_url_test = isset($_GET['surl'])? trim(stripslashes($_GET['surl'])) : false;
234
  if (false !== $search_url_test && '' !== $search_url_test) {
235
  $search_url = $search_url_test;
236
  $search_url_type = isset($_GET['surlt'])? $_GET['surlt'] : false;
237
- if (false !== $search_url_type && !in_array($search_url_type, array_keys(WPLNST_Core_Types::get_url_search_filters())))
238
  $search_url_type = false;
 
239
  }
240
-
241
  // Check search anchor
242
  $search_anchor = $search_anchor_type = false;
243
  $search_anchor_test = isset($_GET['sanc'])? trim(stripslashes($_GET['sanc'])) : false;
244
  if (false !== $search_anchor_test && '' !== $search_anchor_test) {
245
  $search_anchor = $search_anchor_test;
246
  $search_anchor_type = isset($_GET['sanct'])? $_GET['sanct'] : false;
247
- if (false !== $search_anchor_type && !in_array($search_anchor_type, array_keys(WPLNST_Core_Types::get_anchor_search_filters())))
248
  $search_anchor_type = false;
 
249
  }
250
-
251
  // Access scan data
252
  $results = $this->admin->scans->get_scan_results(array(
253
  'scan_id' => $scan->id,
@@ -270,27 +283,28 @@ class WPLNST_Admin_Scans {
270
  'order_date' => $scan->crawl_order,
271
  'paged' => empty($_GET['paged'])? 0 : (int) $_GET['paged'],
272
  ));
273
-
274
  // Unknown error
275
- if (false === $results)
276
  return $this->admin->screen_unknown_error(WPLNST_Admin::get_text('crawler_results'));
277
-
 
278
  // Define all results
279
  $results->is_search = (false !== $object_type) || (false !== $object_post_type) || (false !== $link_type) || (false !== $ignored_type) || (false !== $seo_link_type) || (false !== $protocol_type) || (false !== $special_type) || (false !== $action_type) || (false !== $dest_type) || (false !== $search_url) || (false !== $search_anchor);
280
  $results->is_all_results = (false === $status_code) && (false === $status_level) && !$results->is_search;
281
-
282
  // Check total data
283
  if ($results->total_rows > 0 && $results->is_all_results && (!isset($scan->summary['status_total']) || $scan->summary['status_total'] != $results->total_rows)) {
284
-
285
  // Update total
286
  $scan->summary['status_total'] = $results->total_rows;
287
  $this->admin->scans->update_scan_summary($scan->id, array('status_total' => $scan->summary['status_total']));
288
  }
289
-
290
  // Results properties
291
  $results->scan = $scan;
292
  $results->isolated = false;
293
-
294
  // Results filters
295
  $results->status_code = $status_code;
296
  $results->status_level = $status_level;
@@ -308,10 +322,10 @@ class WPLNST_Admin_Scans {
308
  $results->search_url_type = $search_url_type;
309
  $results->search_anchor = $search_anchor;
310
  $results->search_anchor_type = $search_anchor_type;
311
-
312
  // Custom action view
313
  add_action('wplnst_scans_results_view', array(&$this, 'scans_results_view'));
314
-
315
  // Show admin screen
316
  $this->admin->screen_view(array(
317
  'scans' => $scans,
@@ -329,19 +343,20 @@ class WPLNST_Admin_Scans {
329
  * Extension view to display the scans results list
330
  */
331
  public function scans_results_view($args) {
332
-
333
  // Scan results row actions
334
  add_filter('wplnst_results_actions_url', array(&$this, 'scans_results_actions_url'), 10, 2);
335
  add_filter('wplnst_results_actions_status', array(&$this, 'scans_results_actions_status'), 10, 2);
336
  add_filter('wplnst_results_actions_anchor', array(&$this, 'scans_results_actions_anchor'), 10, 2);
337
-
338
  // Display an isolated scan
339
- if (isset($args['scans']))
340
  $this->scans_list_view(array('scans' => $args['scans']));
341
-
 
342
  // Handle the results view callback
343
  add_action('wplnst_scans_results_view_display', array(&$this, 'scans_results_view_display'));
344
-
345
  // Results list table
346
  $this->scans_results_views_table($args);
347
  }
@@ -371,21 +386,23 @@ class WPLNST_Admin_Scans {
371
  * Define column URL row actions
372
  */
373
  public function scans_results_actions_url($actions, $item) {
374
-
375
  // Check unlinked
376
- if ($item['unlinked'])
377
  return false;
378
-
 
379
  // Check actions var
380
- if (!isset($actions) || !is_array($actions))
381
  $actions = array();
382
-
 
383
  // More actions
384
  $actions = apply_filters('wplnst_results_actions_url_extended', $actions, $item);
385
-
386
  // Visit URL
387
  $actions['wplnst-action-url-visit'] = '<a href="'.esc_url($item['url']).'" target="_blank">'.__('Visit', 'wplnst').'</a>';
388
-
389
  // Done
390
  return $actions;
391
  }
@@ -396,18 +413,20 @@ class WPLNST_Admin_Scans {
396
  * Define column Status row actions
397
  */
398
  public function scans_results_actions_status($actions, $item) {
399
-
400
  // Check unlinked
401
- if ($item['unlinked'])
402
  return false;
403
-
 
404
  // Check actions var
405
- if (!isset($actions) || !is_array($actions))
406
  $actions = array();
407
-
 
408
  // More actions
409
  $actions = apply_filters('wplnst_results_actions_status_extended', $actions, $item);
410
-
411
  // Done
412
  return $actions;
413
  }
@@ -418,18 +437,20 @@ class WPLNST_Admin_Scans {
418
  * Define column Anchor row actions
419
  */
420
  public function scans_results_actions_anchor($actions, $item) {
421
-
422
  // Check unlinked
423
- if ($item['unlinked'])
424
  return false;
425
-
 
426
  // Check actions var
427
- if (!isset($actions) || !is_array($actions))
428
  $actions = array();
429
-
 
430
  // More actions
431
  $actions = apply_filters('wplnst_results_actions_anchor_extended', $actions, $item);
432
-
433
  // Done
434
  return $actions;
435
  }
@@ -445,178 +466,183 @@ class WPLNST_Admin_Scans {
445
  * Attemp to start or stop a crawler
446
  */
447
  private function scans_crawler($scan_id) {
448
-
449
  // Atempt to load scan
450
- if (false === ($scan = $this->admin->get_scan_by_id($scan_id, true)))
451
  return $this->admin->screen_scan_not_found(WPLNST_Admin::get_text('crawler_action'));
452
-
 
453
  // Check valid operation
454
  $operation = empty($_GET['operation'])? false : (in_array($_GET['operation'], array('on', 'off'))? $_GET['operation'] : false);
455
- if (false === $operation)
456
  return $this->admin->screen_invalid_data(WPLNST_Admin::get_text('crawler_action'));
457
-
 
458
  // Initialize
459
  $notice_error = false;
460
  $notice_warning = false;
461
  $notice_success = false;
462
-
463
  // Check nonce
464
  if (empty($_GET['nonce']) || !wp_verify_nonce($_GET['nonce'], 'scan-crawler-'.$scan->hash)) {
465
-
466
  // Not valid data
467
  return $this->admin->screen_invalid_nonce(WPLNST_Admin::get_text('crawler_action'));
468
-
469
  // Check if is playing right now
470
  } elseif ('on' == $operation && 'play' == $scan->status) {
471
-
472
  // Already started
473
  $notice_warning = __('The crawling process for this scan is already started.', 'wplnst');
474
-
475
  // Check if is stopped right now
476
  } elseif ('off' == $operation && in_array($scan->status, array('stop', 'wait'))) {
477
-
478
  // Already started
479
  $notice_warning = __('The crawling process for this scan is already stopped.', 'wplnst');
480
-
481
  // Avoid ended scans
482
  } elseif ('end' == $scan->status) {
483
-
484
  // Not available scan
485
  $notice_warning = __('This scan was completed and it is not possible to start again.', 'wplnst');
486
-
487
  // Check submit form
488
  } else {
489
-
490
  // Stop current scan
491
  if ('off' == $operation) {
492
-
493
  // Remove queued flag if never started
494
  if ('queued' == $scan->status && (empty($scan->row->started_at) || '0000-00-00 00:00:00' == $scan->row->started_at)) {
495
-
496
  // Start current scan
497
  if (!$this->admin->scans->unqueue_scan($scan->id)) {
498
-
499
  // Something failed
500
  $notice_error = __('Something went wrong and the unqueue process was failed.', 'wplnst');
501
-
502
  // Done
503
  } else {
504
-
505
  // Updated
506
  $notice_success = __('The crawler for this scan is back to the wait mode.', 'wplnst');
507
  }
508
-
509
  // Normal mode
510
  } else {
511
-
512
  // Start current scan
513
  if (!$this->admin->scans->stop_scan($scan->id)) {
514
-
515
  // Something failed
516
  $notice_error = __('Something went wront and the crawler stop was failed.', 'wplnst');
517
-
518
  // Done
519
  } else {
520
-
521
  // Updated
522
  $notice_success = sprintf(__('The crawler for this scan is stopped. You can see its collected data in the <a href="%s">crawler results page</a>.', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan_id)));
523
  }
524
  }
525
-
526
  // Run when cURL enabled
527
  } elseif (wplnst_is_curl_enabled()) {
528
-
529
  // Check max scans running
530
  if (!$this->admin->scans->can_play_more_scans()) {
531
-
532
  // Max scans allowed
533
  $notice_error = WPLNST_Admin::get_text('max_scans');
534
-
535
  // Queue scan
536
  $this->admin->scans->queue_scan($scan->id);
537
-
538
  // Check scan ready
539
  } elseif (!$scan->ready) {
540
-
541
  // Something failed
542
  $notice_error = sprintf(__('You need to complete some critical values before start the crawler, please <a href="%s">edit this scan</a>.', 'wplnst'), WPLNST_Core_Plugin::get_url_scans_edit($scan->id));
543
-
544
  // Start attempt
545
  } else {
546
-
547
  // Not continued
548
  $continued = false;
549
-
550
  // Register stopped time
551
  if ('stop' == $scan->status || 'queued' == $scan->status) {
552
-
553
  // Needed to be started before
554
  if (empty($scan->row->started_at) || '0000-00-00 00:00:00' == $scan->row->started_at) {
555
-
556
  // Remove stopped time
557
  $this->admin->scans->remove_stopped_time($scan->id);
558
  $this->admin->scans->update_scan_summary($scan->id, array('time_stopped' => 0));
559
-
560
  // Check stopped time
561
  } elseif (!empty($scan->row->stopped_at) && '0000-00-00 00:00:00' != $scan->row->stopped_at) {
562
-
563
  // Continued
564
  $continued = true;
565
-
566
  // Calculate stopped time
567
  $time_stopped = time() - strtotime($scan->row->stopped_at.' UTC');
568
  $summary = $this->admin->scans->get_scan_summary($scan->id);
569
  $time_stopped += isset($summary['time_stopped'])? (int) $summary['time_stopped'] : 0;
570
  }
571
  }
572
-
573
  // Start current scan
574
  if (!$this->admin->scans->play_scan($scan->id, $continued)) {
575
-
576
  // Something failed
577
  $notice_error = __('Something went wront and the crawler start was failed.', 'wplnst');
578
-
579
  // Done
580
  } else {
581
-
582
  // Check salt file
583
- if (empty($notice_warning) && !WPLNST_Core_Nonce::check_salt_file())
584
  $notice_warning = WPLNST_Admin::get_text('no_salt');
585
-
 
586
  // Update stopped time
587
- if (isset($time_stopped))
588
  $this->admin->scans->update_scan_summary($scan->id, array('time_stopped' => $time_stopped));
589
-
 
590
  // Save default threads values
591
  $this->admin->scans->set_scan_final_threads_options($scan->id, array(
592
  'max_threads' => $scan->threads->max,
593
  'connect_timeout' => $scan->threads->connect_timeout,
594
  'request_timeout' => $scan->threads->request_timeout,
595
  ));
596
-
597
  // Start process now if are not running scans
598
  $this->scans_crawler_run($scan->id, $scan->hash);
599
-
600
  // Updated
601
  $notice_success = sprintf(__('The crawler is running, you can see its data in the <a href="%s">crawler results page</a>.', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan_id)));
602
  }
603
  }
604
  }
605
  }
606
-
607
  // Reload scan
608
- if (false === ($scan = $this->admin->get_scan_by_id($scan_id, true, true)))
609
  return $this->admin->screen_scan_not_found(WPLNST_Admin::get_text('crawler_action'));
610
-
 
611
  // Prepare scans data
612
  $scans = (object) array(
613
  'isolated' => true,
614
  'rows' => array($scan),
615
  );
616
-
617
  // Custom action view
618
  add_action('wplnst_scans_crawler_view', array(&$this, 'scans_list_view'));
619
-
620
  // Screen showing the start crawling process
621
  $this->admin->screen_view(array(
622
  'scans' => $scans,
@@ -628,7 +654,7 @@ class WPLNST_Admin_Scans {
628
  'add_item_text' => WPLNST_Admin::get_text('scan_new_add'),
629
  'add_item_url' => WPLNST_Core_Plugin::get_url_scans_add(),
630
  ));
631
-
632
  // Check for queued scans
633
  WPLNST_Core_Alive::activity(true);
634
  }
@@ -653,83 +679,89 @@ class WPLNST_Admin_Scans {
653
  * Attemp to remove a scan
654
  */
655
  private function scans_delete($scan_id) {
656
-
657
  // Initialize
658
  $notice_success = false;
659
  $notice_warning = false;
660
-
661
  // Check multiple scans
662
  if (isset($_GET['scan_id']) && '-' == mb_substr($_GET['scan_id'], 0, 1)) {
663
-
664
  // Check nonce
665
- if (empty($_GET['nonce']) || !wp_verify_nonce($_GET['nonce'], 'bulk-scans-delete'))
666
  return $this->admin->screen_invalid_nonce(WPLNST_Admin::get_text('scan_delete'));
667
-
 
668
  // Check confirmation
669
  if (empty($_GET['confirm']) || 'on' != $_GET['confirm']) {
670
-
671
  // Confirm message
672
  $notice_warning = sprintf(__('Sorry, we need a confirmation action. Please click here to <a href="%s" class="wplnst-scan-delete" data-confirm="%s">delete scan</a>', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_delete($_GET['scan_id'], 'bulk-scans-delete')), esc_attr(WPLNST_Admin::get_text('scan_delete_confirm')));
673
-
674
  // Done
675
  } else {
676
-
677
  // Timeouts
678
  set_time_limit(0);
679
-
680
  // Initialize
681
  $scans = array();
682
-
683
  // Extract identifiers
684
  $ids = array_map('intval', explode('-', trim($_GET['scan_id'], '-')));
685
  foreach ($ids as $scan_id) {
686
- if (!empty($scan_id) && false !== ($scan = $this->admin->get_scan_by_id($scan_id)))
687
  $scans[] = $scan_id;
 
688
  }
689
-
690
  // Check data
691
- if (empty($scans))
692
  return $this->admin->screen_invalid_data(WPLNST_Admin::get_text('scan_delete'));
693
-
 
694
  // Enum and remove
695
- foreach ($scans as $scan_id)
696
  $this->admin->scans->delete_scan($scan_id);
 
697
 
698
  // Success message
699
  $notice_success = __('The scans have been removed.', 'wplnst');
700
  }
701
-
702
  // Single
703
  } else {
704
-
705
  // Atempt to load scan
706
- if (false === ($scan = $this->admin->get_scan_by_id($scan_id)))
707
  return $this->admin->screen_scan_not_found(WPLNST_Admin::get_text('scan_delete'));
708
-
 
709
  // Check nonce
710
- if (empty($_GET['nonce']) || !wp_verify_nonce($_GET['nonce'], $scan->hash))
711
  return $this->admin->screen_invalid_nonce(WPLNST_Admin::get_text('scan_delete'));
712
-
 
713
  // Check confirmation
714
  if (empty($_GET['confirm']) || 'on' != $_GET['confirm']) {
715
-
716
  // Confirm message
717
  $notice_warning = sprintf(__('Sorry, we need a confirmation action. Please click here to <a href="%s" class="wplnst-scan-delete-isolated" data-confirm-delete="%s">delete scan</a>', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_delete($scan->id, $scan->hash)), esc_attr(WPLNST_Admin::get_text('scan_delete_confirm')));
718
-
719
  // Done
720
  } else {
721
-
722
  // Remove scan
723
  $this->admin->scans->delete_scan($scan_id);
724
-
725
  // Success message
726
  $notice_success = __('The scan has been removed.', 'wplnst');
727
  }
728
  }
729
-
730
  // Custom action view
731
  add_action('wplnst_scans_delete_view', array(&$this, 'scans_delete_view'));
732
-
733
  // Show admin screen
734
  $this->admin->screen_view(array(
735
  'title' => WPLNST_Admin::get_text('scan_delete'),
@@ -739,7 +771,7 @@ class WPLNST_Admin_Scans {
739
  'add_item_text' => WPLNST_Admin::get_text('scan_new_add'),
740
  'add_item_url' => WPLNST_Core_Plugin::get_url_scans_add(),
741
  ));
742
-
743
  // Check for queued scans
744
  WPLNST_Core_Alive::activity(true);
745
  }
@@ -750,7 +782,7 @@ class WPLNST_Admin_Scans {
750
  * Extension view when scan deleted
751
  */
752
  public function scans_delete_view($args) {
753
-
754
  // Back to the scans screen
755
  echo '<p>&nbsp;&nbsp; &laquo; <a href="'.WPLNST_Core_Plugin::get_url_scans().'">'.__('Back to the scans list', 'wplnst').'</a></p>';
756
  }
@@ -766,16 +798,16 @@ class WPLNST_Admin_Scans {
766
  * New or edit scan
767
  */
768
  private function scans_edit($scan_id = 0) {
769
-
770
  // Scans library
771
  $this->admin->load_scans_object();
772
-
773
  // Notice initialization
774
  $notice_error = isset($this->admin->scan_submit)? $this->admin->scan_submit->notice_error : false;
775
  $notice_warning = isset($this->admin->scan_submit)? $this->admin->scan_submit->notice_warning : false;
776
  $notice_success = isset($this->admin->scan_submit)? $this->admin->scan_submit->notice_success : false;
777
  $notice_crawler = isset($this->admin->scan_submit)? $this->admin->scan_submit->notice_crawler : false;
778
-
779
  // Check submit error
780
  if ($notice_error) {
781
  return $this->admin->screen_view(array(
@@ -783,59 +815,61 @@ class WPLNST_Admin_Scans {
783
  'notice_error' => $notice_error,
784
  ));
785
  }
786
-
787
  // Check existing scan
788
  if (!empty($scan_id)) {
789
-
790
  // Atempt to load scan
791
- if (false === ($scan = $this->admin->get_scan_by_id($scan_id, true)))
792
  return $this->admin->screen_scan_not_found(WPLNST_Admin::get_text('scan_edit'));
793
-
 
794
  // Check update
795
  if (!$notice_success && !empty($_GET['updated']) && 'on' == $_GET['updated']) {
796
-
797
  // New scan created
798
  $notice_success = __('New scan added successfully.', 'wplnst');
799
-
800
  // Check started argument
801
  if (!empty($_GET['started'])) {
802
-
803
  // Check max scans
804
  if ('max_scans' == $_GET['started']) {
805
-
806
  // Warning message
807
  $notice_warning = WPLNST_Admin::get_text('max_scans');
808
-
809
  // Check error
810
  } elseif ('error' == $_GET['started']) {
811
-
812
  // Warning message
813
  $notice_warning = sprintf(__('Something went wrong trying to start the crawler for this new scan.'));
814
-
815
  // Scan running
816
  } elseif ('on' == $_GET['started']) {
817
-
818
  // New crawler running
819
  $notice_crawler = sprintf(__('The crawler for this new scan is running. You can see its data in the <a href="%s">crawler results page</a>.', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan_id)));
820
  }
821
-
822
  // Not started
823
  } elseif ('wait' == $scan->status && $this->admin->scans->can_play_more_scans() && true === $this->admin->scans->is_scan_ready($scan)) {
824
-
825
  // Invite to start the crawler
826
  $start_url = esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($scan->id, 'on', $scan->hash));
827
  $notice_success .= ' '.sprintf(__('From now on you can <a href="%s">start the crawler</a>.', 'wplnst'), $start_url);
828
  }
829
  }
830
-
831
  // Check salt file
832
- if ('play' == $scan->status && empty($notice_warning) && !WPLNST_Core_Nonce::check_salt_file())
833
  $notice_warning = WPLNST_Admin::get_text('no_salt');
 
834
  }
835
-
836
  // Default values
837
  if (empty($scan)) {
838
-
839
  // Prepare scan object
840
  $scan = (object) array(
841
  'id' => 0,
@@ -867,26 +901,28 @@ class WPLNST_Admin_Scans {
867
  'connect_timeout' => 0,
868
  'request_timeout' => 0,
869
  );
870
-
871
  // Check scan
872
  } else {
873
-
874
  // Analyze data
875
  $ready = $this->admin->scans->is_scan_ready($scan);
876
  $is_ready = (true === $ready);
877
-
878
  // Prepare notifications
879
- if (!$is_ready)
880
  $notice_ready = $ready;
881
-
 
882
  // Check ready update
883
- if ($scan->ready != $is_ready)
884
  $this->admin->scans->update_scan_ready($scan->id, $is_ready);
 
885
  }
886
-
887
  // Custom action view
888
  add_action('wplnst_scans_edit_view', array(&$this, 'scans_edit_view'));
889
-
890
  // Display page
891
  $this->admin->screen_view(array(
892
  'scan' => $scan,
1
  <?php
2
 
3
  /**
4
+ * Admin Scans class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Admin
8
  */
9
  class WPLNST_Admin_Scans {
10
 
31
  * Constructor
32
  */
33
  public function __construct(&$admin, $menu) {
34
+
35
  // Copy parent
36
  $this->admin = &$admin;
37
+
38
  // Scans menu
39
  if ('context' == $menu) {
40
  $this->scans_context();
41
+
42
  // Check edit scan menu
43
  } elseif ('edit' == $menu) {
44
  $this->scans_edit();
51
  * Scans menu
52
  */
53
  private function scans_context() {
54
+
55
  // Check context
56
  $context = empty($_GET['context'])? false : $_GET['context'];
57
+
58
  // Check scan id parameter
59
  $scan_id = empty($_GET['scan_id'])? 0 : (int) $_GET['scan_id'];
60
+
61
  // Results context
62
  if ('results' == $context) {
63
+
64
  // Crawl results
65
  $this->scans_results($scan_id);
66
+
67
  // Crawling order
68
  } elseif ('crawler' == $context) {
69
+
70
  // Crawl check
71
  $this->scans_crawler($scan_id);
72
+
73
  // Delete context
74
  } elseif ('delete' == $context) {
75
+
76
  // Delete confirm
77
  $this->scans_delete($scan_id);
78
+
79
  // Edit
80
  } elseif ('edit' == $context) {
81
+
82
  // Show edit view
83
  $this->scans_edit($scan_id);
84
+
85
  // Default
86
  } else {
87
+
88
  // List of scans
89
  $this->scans_list();
90
  }
101
  * Prepare the list of scans
102
  */
103
  private function scans_list() {
104
+
105
  // Retrieve scans
106
  $scans = $this->admin->get_scans(array(
107
  'setup_names' => true,
108
  'order_by' => 'FIELD(status, "play", "wait", "queued", "stop", "end"), started_at DESC, enqueued_at ASC, created_at DESC',
109
  'paged' => empty($_GET['paged'])? 0 : (int) $_GET['paged'],
110
  ));
111
+
112
  // No isolated mode
113
  $scans->isolated = false;
114
+
115
  // Custom action view
116
  add_action('wplnst_scans_list_view', array(&$this, 'scans_list_view'));
117
+
118
  // Show admin screen
119
  $this->admin->screen_view(array(
120
  'scans' => $scans,
130
  * Extension view to display the scans list
131
  */
132
  public function scans_list_view($args) {
133
+
134
  // Dependencies
135
  wplnst_require('views', 'scans');
136
+
137
  // Display table
138
  $list = new WPLNST_Views_Scans($args['scans']);
139
  $list->prepare_items();
151
  * Prepare and display crawling results
152
  */
153
  private function scans_results($scan_id) {
154
+
155
  // Atempt to load scan
156
+ if (false === ($scan = $this->admin->get_scan_by_id($scan_id, true))) {
157
  return $this->admin->screen_scan_not_found(WPLNST_Admin::get_text('crawler_results'));
158
+ }
159
+
160
  // Prepare scans data
161
  $scans = (object) array(
162
  'isolated' => true,
163
  'rows' => array($scan),
164
  );
165
+
166
  // Check status param
167
  $status_code = $status_level = false;
168
  $status_test = isset($_GET['status'])? $_GET['status'] : false;
169
  if (false !== $status_test) {
170
  if (1 == strlen($status_test)) {
171
+ if ('0' == $status_test || in_array($status_test, $scan->status_levels)) {
172
  $status_level = $status_test;
173
+ }
174
  } elseif (3 == strlen($status_test)) {
175
  $status_code = $status_test;
176
  }
177
  }
178
+
179
  // Check object type param
180
  $object_post_type = false;
181
  $object_type = isset($_GET['otype'])? $_GET['otype'] : false;
183
  if (!in_array($object_type, array_keys(WPLNST_Core_Types::get_objects_types()))) {
184
  if (0 === strpos($object_type, 'posts_') && strlen($object_type) > 6) {
185
  $object_post_type_test = mb_substr($object_type, 6);
186
+ if (in_array($object_post_type_test, $scan->post_types)) {
187
  $object_post_type = $object_post_type_test;
188
+ }
189
  }
190
  $object_type = false;
191
  }
192
  }
193
+
194
  // Check link type param
195
  $link_type = isset($_GET['ltype'])? $_GET['ltype'] : false;
196
+ if (false !== $link_type && !in_array($link_type, array_keys(WPLNST_Core_Types::get_link_types()))) {
197
  $link_type = false;
198
+ }
199
 
200
  // Check ignored or not
201
  $ignored_type = isset($_GET['ig'])? $_GET['ig'] : false;
202
+ if (false !== $ignored_type && !in_array($ignored_type, array_keys(WPLNST_Core_Types::get_ignored_types()))) {
203
  $ignored_type = false;
204
+ }
205
+
206
  // Check SEO links
207
  $seo_link_type = isset($_GET['slt'])? $_GET['slt'] : false;
208
+ if (false !== $seo_link_type && !in_array($seo_link_type, array_keys(WPLNST_Core_Types::get_seo_link_types()))) {
209
  $seo_link_type = false;
210
+ }
211
+
212
  // Check protocol
213
  $protocol_type = isset($_GET['pt'])? $_GET['pt'] : false;
214
+ if (false !== $protocol_type && !in_array($protocol_type, array_keys(WPLNST_Core_Types::get_protocol_types()))) {
215
  $protocol_type = false;
216
+ }
217
+
218
  // Check special
219
  $special_type = isset($_GET['sp'])? $_GET['sp'] : false;
220
+ if (false !== $special_type && !in_array($special_type, array_keys(WPLNST_Core_Types::get_special_types()))) {
221
  $special_type = false;
222
+ }
223
+
224
  // Check action
225
  $action_type = isset($_GET['ac'])? $_GET['ac'] : false;
226
+ if (false !== $action_type && !in_array($action_type, array_keys(WPLNST_Core_Types::get_action_types()))) {
227
  $action_type = false;
228
+ }
229
+
230
  // Check destination
231
  $dest_type = isset($_GET['dtype'])? $_GET['dtype'] : false;
232
+ if (false !== $dest_type && !in_array($dest_type, array_keys(WPLNST_Core_Types::get_destination_types()))) {
233
  $dest_type = false;
234
+ }
235
+
236
  // Check order
237
  $order_type = isset($_GET['or'])? $_GET['or'] : false;
238
+ if (false !== $order_type && !in_array($order_type, array_keys(WPLNST_Core_Types::get_crawl_order())) && !in_array($order_type, array_keys(WPLNST_Core_Types::get_order_types()))) {
239
  $order_type = false;
240
+ }
241
+
242
  // Check search URL
243
  $search_url = $search_url_type = false;
244
  $search_url_test = isset($_GET['surl'])? trim(stripslashes($_GET['surl'])) : false;
245
  if (false !== $search_url_test && '' !== $search_url_test) {
246
  $search_url = $search_url_test;
247
  $search_url_type = isset($_GET['surlt'])? $_GET['surlt'] : false;
248
+ if (false !== $search_url_type && !in_array($search_url_type, array_keys(WPLNST_Core_Types::get_url_search_filters()))) {
249
  $search_url_type = false;
250
+ }
251
  }
252
+
253
  // Check search anchor
254
  $search_anchor = $search_anchor_type = false;
255
  $search_anchor_test = isset($_GET['sanc'])? trim(stripslashes($_GET['sanc'])) : false;
256
  if (false !== $search_anchor_test && '' !== $search_anchor_test) {
257
  $search_anchor = $search_anchor_test;
258
  $search_anchor_type = isset($_GET['sanct'])? $_GET['sanct'] : false;
259
+ if (false !== $search_anchor_type && !in_array($search_anchor_type, array_keys(WPLNST_Core_Types::get_anchor_search_filters()))) {
260
  $search_anchor_type = false;
261
+ }
262
  }
263
+
264
  // Access scan data
265
  $results = $this->admin->scans->get_scan_results(array(
266
  'scan_id' => $scan->id,
283
  'order_date' => $scan->crawl_order,
284
  'paged' => empty($_GET['paged'])? 0 : (int) $_GET['paged'],
285
  ));
286
+
287
  // Unknown error
288
+ if (false === $results) {
289
  return $this->admin->screen_unknown_error(WPLNST_Admin::get_text('crawler_results'));
290
+ }
291
+
292
  // Define all results
293
  $results->is_search = (false !== $object_type) || (false !== $object_post_type) || (false !== $link_type) || (false !== $ignored_type) || (false !== $seo_link_type) || (false !== $protocol_type) || (false !== $special_type) || (false !== $action_type) || (false !== $dest_type) || (false !== $search_url) || (false !== $search_anchor);
294
  $results->is_all_results = (false === $status_code) && (false === $status_level) && !$results->is_search;
295
+
296
  // Check total data
297
  if ($results->total_rows > 0 && $results->is_all_results && (!isset($scan->summary['status_total']) || $scan->summary['status_total'] != $results->total_rows)) {
298
+
299
  // Update total
300
  $scan->summary['status_total'] = $results->total_rows;
301
  $this->admin->scans->update_scan_summary($scan->id, array('status_total' => $scan->summary['status_total']));
302
  }
303
+
304
  // Results properties
305
  $results->scan = $scan;
306
  $results->isolated = false;
307
+
308
  // Results filters
309
  $results->status_code = $status_code;
310
  $results->status_level = $status_level;
322
  $results->search_url_type = $search_url_type;
323
  $results->search_anchor = $search_anchor;
324
  $results->search_anchor_type = $search_anchor_type;
325
+
326
  // Custom action view
327
  add_action('wplnst_scans_results_view', array(&$this, 'scans_results_view'));
328
+
329
  // Show admin screen
330
  $this->admin->screen_view(array(
331
  'scans' => $scans,
343
  * Extension view to display the scans results list
344
  */
345
  public function scans_results_view($args) {
346
+
347
  // Scan results row actions
348
  add_filter('wplnst_results_actions_url', array(&$this, 'scans_results_actions_url'), 10, 2);
349
  add_filter('wplnst_results_actions_status', array(&$this, 'scans_results_actions_status'), 10, 2);
350
  add_filter('wplnst_results_actions_anchor', array(&$this, 'scans_results_actions_anchor'), 10, 2);
351
+
352
  // Display an isolated scan
353
+ if (isset($args['scans'])) {
354
  $this->scans_list_view(array('scans' => $args['scans']));
355
+ }
356
+
357
  // Handle the results view callback
358
  add_action('wplnst_scans_results_view_display', array(&$this, 'scans_results_view_display'));
359
+
360
  // Results list table
361
  $this->scans_results_views_table($args);
362
  }
386
  * Define column URL row actions
387
  */
388
  public function scans_results_actions_url($actions, $item) {
389
+
390
  // Check unlinked
391
+ if ($item['unlinked']) {
392
  return false;
393
+ }
394
+
395
  // Check actions var
396
+ if (!isset($actions) || !is_array($actions)) {
397
  $actions = array();
398
+ }
399
+
400
  // More actions
401
  $actions = apply_filters('wplnst_results_actions_url_extended', $actions, $item);
402
+
403
  // Visit URL
404
  $actions['wplnst-action-url-visit'] = '<a href="'.esc_url($item['url']).'" target="_blank">'.__('Visit', 'wplnst').'</a>';
405
+
406
  // Done
407
  return $actions;
408
  }
413
  * Define column Status row actions
414
  */
415
  public function scans_results_actions_status($actions, $item) {
416
+
417
  // Check unlinked
418
+ if ($item['unlinked']) {
419
  return false;
420
+ }
421
+
422
  // Check actions var
423
+ if (!isset($actions) || !is_array($actions)) {
424
  $actions = array();
425
+ }
426
+
427
  // More actions
428
  $actions = apply_filters('wplnst_results_actions_status_extended', $actions, $item);
429
+
430
  // Done
431
  return $actions;
432
  }
437
  * Define column Anchor row actions
438
  */
439
  public function scans_results_actions_anchor($actions, $item) {
440
+
441
  // Check unlinked
442
+ if ($item['unlinked']) {
443
  return false;
444
+ }
445
+
446
  // Check actions var
447
+ if (!isset($actions) || !is_array($actions)) {
448
  $actions = array();
449
+ }
450
+
451
  // More actions
452
  $actions = apply_filters('wplnst_results_actions_anchor_extended', $actions, $item);
453
+
454
  // Done
455
  return $actions;
456
  }
466
  * Attemp to start or stop a crawler
467
  */
468
  private function scans_crawler($scan_id) {
469
+
470
  // Atempt to load scan
471
+ if (false === ($scan = $this->admin->get_scan_by_id($scan_id, true))) {
472
  return $this->admin->screen_scan_not_found(WPLNST_Admin::get_text('crawler_action'));
473
+ }
474
+
475
  // Check valid operation
476
  $operation = empty($_GET['operation'])? false : (in_array($_GET['operation'], array('on', 'off'))? $_GET['operation'] : false);
477
+ if (false === $operation) {
478
  return $this->admin->screen_invalid_data(WPLNST_Admin::get_text('crawler_action'));
479
+ }
480
+
481
  // Initialize
482
  $notice_error = false;
483
  $notice_warning = false;
484
  $notice_success = false;
485
+
486
  // Check nonce
487
  if (empty($_GET['nonce']) || !wp_verify_nonce($_GET['nonce'], 'scan-crawler-'.$scan->hash)) {
488
+
489
  // Not valid data
490
  return $this->admin->screen_invalid_nonce(WPLNST_Admin::get_text('crawler_action'));
491
+
492
  // Check if is playing right now
493
  } elseif ('on' == $operation && 'play' == $scan->status) {
494
+
495
  // Already started
496
  $notice_warning = __('The crawling process for this scan is already started.', 'wplnst');
497
+
498
  // Check if is stopped right now
499
  } elseif ('off' == $operation && in_array($scan->status, array('stop', 'wait'))) {
500
+
501
  // Already started
502
  $notice_warning = __('The crawling process for this scan is already stopped.', 'wplnst');
503
+
504
  // Avoid ended scans
505
  } elseif ('end' == $scan->status) {
506
+
507
  // Not available scan
508
  $notice_warning = __('This scan was completed and it is not possible to start again.', 'wplnst');
509
+
510
  // Check submit form
511
  } else {
512
+
513
  // Stop current scan
514
  if ('off' == $operation) {
515
+
516
  // Remove queued flag if never started
517
  if ('queued' == $scan->status && (empty($scan->row->started_at) || '0000-00-00 00:00:00' == $scan->row->started_at)) {
518
+
519
  // Start current scan
520
  if (!$this->admin->scans->unqueue_scan($scan->id)) {
521
+
522
  // Something failed
523
  $notice_error = __('Something went wrong and the unqueue process was failed.', 'wplnst');
524
+
525
  // Done
526
  } else {
527
+
528
  // Updated
529
  $notice_success = __('The crawler for this scan is back to the wait mode.', 'wplnst');
530
  }
531
+
532
  // Normal mode
533
  } else {
534
+
535
  // Start current scan
536
  if (!$this->admin->scans->stop_scan($scan->id)) {
537
+
538
  // Something failed
539
  $notice_error = __('Something went wront and the crawler stop was failed.', 'wplnst');
540
+
541
  // Done
542
  } else {
543
+
544
  // Updated
545
  $notice_success = sprintf(__('The crawler for this scan is stopped. You can see its collected data in the <a href="%s">crawler results page</a>.', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan_id)));
546
  }
547
  }
548
+
549
  // Run when cURL enabled
550
  } elseif (wplnst_is_curl_enabled()) {
551
+
552
  // Check max scans running
553
  if (!$this->admin->scans->can_play_more_scans()) {
554
+
555
  // Max scans allowed
556
  $notice_error = WPLNST_Admin::get_text('max_scans');
557
+
558
  // Queue scan
559
  $this->admin->scans->queue_scan($scan->id);
560
+
561
  // Check scan ready
562
  } elseif (!$scan->ready) {
563
+
564
  // Something failed
565
  $notice_error = sprintf(__('You need to complete some critical values before start the crawler, please <a href="%s">edit this scan</a>.', 'wplnst'), WPLNST_Core_Plugin::get_url_scans_edit($scan->id));
566
+
567
  // Start attempt
568
  } else {
569
+
570
  // Not continued
571
  $continued = false;
572
+
573
  // Register stopped time
574
  if ('stop' == $scan->status || 'queued' == $scan->status) {
575
+
576
  // Needed to be started before
577
  if (empty($scan->row->started_at) || '0000-00-00 00:00:00' == $scan->row->started_at) {
578
+
579
  // Remove stopped time
580
  $this->admin->scans->remove_stopped_time($scan->id);
581
  $this->admin->scans->update_scan_summary($scan->id, array('time_stopped' => 0));
582
+
583
  // Check stopped time
584
  } elseif (!empty($scan->row->stopped_at) && '0000-00-00 00:00:00' != $scan->row->stopped_at) {
585
+
586
  // Continued
587
  $continued = true;
588
+
589
  // Calculate stopped time
590
  $time_stopped = time() - strtotime($scan->row->stopped_at.' UTC');
591
  $summary = $this->admin->scans->get_scan_summary($scan->id);
592
  $time_stopped += isset($summary['time_stopped'])? (int) $summary['time_stopped'] : 0;
593
  }
594
  }
595
+
596
  // Start current scan
597
  if (!$this->admin->scans->play_scan($scan->id, $continued)) {
598
+
599
  // Something failed
600
  $notice_error = __('Something went wront and the crawler start was failed.', 'wplnst');
601
+
602
  // Done
603
  } else {
604
+
605
  // Check salt file
606
+ if (empty($notice_warning) && !WPLNST_Core_Nonce::check_salt_file()) {
607
  $notice_warning = WPLNST_Admin::get_text('no_salt');
608
+ }
609
+
610
  // Update stopped time
611
+ if (isset($time_stopped)) {
612
  $this->admin->scans->update_scan_summary($scan->id, array('time_stopped' => $time_stopped));
613
+ }
614
+
615
  // Save default threads values
616
  $this->admin->scans->set_scan_final_threads_options($scan->id, array(
617
  'max_threads' => $scan->threads->max,
618
  'connect_timeout' => $scan->threads->connect_timeout,
619
  'request_timeout' => $scan->threads->request_timeout,
620
  ));
621
+
622
  // Start process now if are not running scans
623
  $this->scans_crawler_run($scan->id, $scan->hash);
624
+
625
  // Updated
626
  $notice_success = sprintf(__('The crawler is running, you can see its data in the <a href="%s">crawler results page</a>.', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan_id)));
627
  }
628
  }
629
  }
630
  }
631
+
632
  // Reload scan
633
+ if (false === ($scan = $this->admin->get_scan_by_id($scan_id, true, true))) {
634
  return $this->admin->screen_scan_not_found(WPLNST_Admin::get_text('crawler_action'));
635
+ }
636
+
637
  // Prepare scans data
638
  $scans = (object) array(
639
  'isolated' => true,
640
  'rows' => array($scan),
641
  );
642
+
643
  // Custom action view
644
  add_action('wplnst_scans_crawler_view', array(&$this, 'scans_list_view'));
645
+
646
  // Screen showing the start crawling process
647
  $this->admin->screen_view(array(
648
  'scans' => $scans,
654
  'add_item_text' => WPLNST_Admin::get_text('scan_new_add'),
655
  'add_item_url' => WPLNST_Core_Plugin::get_url_scans_add(),
656
  ));
657
+
658
  // Check for queued scans
659
  WPLNST_Core_Alive::activity(true);
660
  }
679
  * Attemp to remove a scan
680
  */
681
  private function scans_delete($scan_id) {
682
+
683
  // Initialize
684
  $notice_success = false;
685
  $notice_warning = false;
686
+
687
  // Check multiple scans
688
  if (isset($_GET['scan_id']) && '-' == mb_substr($_GET['scan_id'], 0, 1)) {
689
+
690
  // Check nonce
691
+ if (empty($_GET['nonce']) || !wp_verify_nonce($_GET['nonce'], 'bulk-scans-delete')) {
692
  return $this->admin->screen_invalid_nonce(WPLNST_Admin::get_text('scan_delete'));
693
+ }
694
+
695
  // Check confirmation
696
  if (empty($_GET['confirm']) || 'on' != $_GET['confirm']) {
697
+
698
  // Confirm message
699
  $notice_warning = sprintf(__('Sorry, we need a confirmation action. Please click here to <a href="%s" class="wplnst-scan-delete" data-confirm="%s">delete scan</a>', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_delete($_GET['scan_id'], 'bulk-scans-delete')), esc_attr(WPLNST_Admin::get_text('scan_delete_confirm')));
700
+
701
  // Done
702
  } else {
703
+
704
  // Timeouts
705
  set_time_limit(0);
706
+
707
  // Initialize
708
  $scans = array();
709
+
710
  // Extract identifiers
711
  $ids = array_map('intval', explode('-', trim($_GET['scan_id'], '-')));
712
  foreach ($ids as $scan_id) {
713
+ if (!empty($scan_id) && false !== ($scan = $this->admin->get_scan_by_id($scan_id))) {
714
  $scans[] = $scan_id;
715
+ }
716
  }
717
+
718
  // Check data
719
+ if (empty($scans)) {
720
  return $this->admin->screen_invalid_data(WPLNST_Admin::get_text('scan_delete'));
721
+ }
722
+
723
  // Enum and remove
724
+ foreach ($scans as $scan_id) {
725
  $this->admin->scans->delete_scan($scan_id);
726
+ }
727
 
728
  // Success message
729
  $notice_success = __('The scans have been removed.', 'wplnst');
730
  }
731
+
732
  // Single
733
  } else {
734
+
735
  // Atempt to load scan
736
+ if (false === ($scan = $this->admin->get_scan_by_id($scan_id))) {
737
  return $this->admin->screen_scan_not_found(WPLNST_Admin::get_text('scan_delete'));
738
+ }
739
+
740
  // Check nonce
741
+ if (empty($_GET['nonce']) || !wp_verify_nonce($_GET['nonce'], $scan->hash)) {
742
  return $this->admin->screen_invalid_nonce(WPLNST_Admin::get_text('scan_delete'));
743
+ }
744
+
745
  // Check confirmation
746
  if (empty($_GET['confirm']) || 'on' != $_GET['confirm']) {
747
+
748
  // Confirm message
749
  $notice_warning = sprintf(__('Sorry, we need a confirmation action. Please click here to <a href="%s" class="wplnst-scan-delete-isolated" data-confirm-delete="%s">delete scan</a>', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_delete($scan->id, $scan->hash)), esc_attr(WPLNST_Admin::get_text('scan_delete_confirm')));
750
+
751
  // Done
752
  } else {
753
+
754
  // Remove scan
755
  $this->admin->scans->delete_scan($scan_id);
756
+
757
  // Success message
758
  $notice_success = __('The scan has been removed.', 'wplnst');
759
  }
760
  }
761
+
762
  // Custom action view
763
  add_action('wplnst_scans_delete_view', array(&$this, 'scans_delete_view'));
764
+
765
  // Show admin screen
766
  $this->admin->screen_view(array(
767
  'title' => WPLNST_Admin::get_text('scan_delete'),
771
  'add_item_text' => WPLNST_Admin::get_text('scan_new_add'),
772
  'add_item_url' => WPLNST_Core_Plugin::get_url_scans_add(),
773
  ));
774
+
775
  // Check for queued scans
776
  WPLNST_Core_Alive::activity(true);
777
  }
782
  * Extension view when scan deleted
783
  */
784
  public function scans_delete_view($args) {
785
+
786
  // Back to the scans screen
787
  echo '<p>&nbsp;&nbsp; &laquo; <a href="'.WPLNST_Core_Plugin::get_url_scans().'">'.__('Back to the scans list', 'wplnst').'</a></p>';
788
  }
798
  * New or edit scan
799
  */
800
  private function scans_edit($scan_id = 0) {
801
+
802
  // Scans library
803
  $this->admin->load_scans_object();
804
+
805
  // Notice initialization
806
  $notice_error = isset($this->admin->scan_submit)? $this->admin->scan_submit->notice_error : false;
807
  $notice_warning = isset($this->admin->scan_submit)? $this->admin->scan_submit->notice_warning : false;
808
  $notice_success = isset($this->admin->scan_submit)? $this->admin->scan_submit->notice_success : false;
809
  $notice_crawler = isset($this->admin->scan_submit)? $this->admin->scan_submit->notice_crawler : false;
810
+
811
  // Check submit error
812
  if ($notice_error) {
813
  return $this->admin->screen_view(array(
815
  'notice_error' => $notice_error,
816
  ));
817
  }
818
+
819
  // Check existing scan
820
  if (!empty($scan_id)) {
821
+
822
  // Atempt to load scan
823
+ if (false === ($scan = $this->admin->get_scan_by_id($scan_id, true))) {
824
  return $this->admin->screen_scan_not_found(WPLNST_Admin::get_text('scan_edit'));
825
+ }
826
+
827
  // Check update
828
  if (!$notice_success && !empty($_GET['updated']) && 'on' == $_GET['updated']) {
829
+
830
  // New scan created
831
  $notice_success = __('New scan added successfully.', 'wplnst');
832
+
833
  // Check started argument
834
  if (!empty($_GET['started'])) {
835
+
836
  // Check max scans
837
  if ('max_scans' == $_GET['started']) {
838
+
839
  // Warning message
840
  $notice_warning = WPLNST_Admin::get_text('max_scans');
841
+
842
  // Check error
843
  } elseif ('error' == $_GET['started']) {
844
+
845
  // Warning message
846
  $notice_warning = sprintf(__('Something went wrong trying to start the crawler for this new scan.'));
847
+
848
  // Scan running
849
  } elseif ('on' == $_GET['started']) {
850
+
851
  // New crawler running
852
  $notice_crawler = sprintf(__('The crawler for this new scan is running. You can see its data in the <a href="%s">crawler results page</a>.', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan_id)));
853
  }
854
+
855
  // Not started
856
  } elseif ('wait' == $scan->status && $this->admin->scans->can_play_more_scans() && true === $this->admin->scans->is_scan_ready($scan)) {
857
+
858
  // Invite to start the crawler
859
  $start_url = esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($scan->id, 'on', $scan->hash));
860
  $notice_success .= ' '.sprintf(__('From now on you can <a href="%s">start the crawler</a>.', 'wplnst'), $start_url);
861
  }
862
  }
863
+
864
  // Check salt file
865
+ if ('play' == $scan->status && empty($notice_warning) && !WPLNST_Core_Nonce::check_salt_file()) {
866
  $notice_warning = WPLNST_Admin::get_text('no_salt');
867
+ }
868
  }
869
+
870
  // Default values
871
  if (empty($scan)) {
872
+
873
  // Prepare scan object
874
  $scan = (object) array(
875
  'id' => 0,
901
  'connect_timeout' => 0,
902
  'request_timeout' => 0,
903
  );
904
+
905
  // Check scan
906
  } else {
907
+
908
  // Analyze data
909
  $ready = $this->admin->scans->is_scan_ready($scan);
910
  $is_ready = (true === $ready);
911
+
912
  // Prepare notifications
913
+ if (!$is_ready) {
914
  $notice_ready = $ready;
915
+ }
916
+
917
  // Check ready update
918
+ if ($scan->ready != $is_ready) {
919
  $this->admin->scans->update_scan_ready($scan->id, $is_ready);
920
+ }
921
  }
922
+
923
  // Custom action view
924
  add_action('wplnst_scans_edit_view', array(&$this, 'scans_edit_view'));
925
+
926
  // Display page
927
  $this->admin->screen_view(array(
928
  'scan' => $scan,
admin/settings.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Admin Settings class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Admin
8
  */
9
  class WPLNST_Admin_Settings {
10
 
@@ -14,17 +14,18 @@ class WPLNST_Admin_Settings {
14
  * Constructor
15
  */
16
  public function __construct(&$admin) {
17
-
18
  // Initialize
19
  $notice_success = $notice_error = false;
20
-
21
  // Check submit
22
  if (isset($_POST['settings_nonce'])) {
23
-
24
  // Check nonce
25
- if (!wp_verify_nonce($_POST['settings_nonce'], WPLNST_Core_Plugin::slug.'-settings'))
26
  return $admin->screen_invalid_nonce(WPLNST_Admin::get_text('settings'));
27
-
 
28
  // General update
29
  update_option('wplnst_max_threads', (int) $_POST['tx-max-threads']);
30
  update_option('wplnst_max_scans', (int) $_POST['tx-max-scans']);
@@ -33,7 +34,7 @@ class WPLNST_Admin_Settings {
33
  update_option('wplnst_max_redirs', (int) $_POST['tx-max-redirs']);
34
  update_option('wplnst_max_download', (int) $_POST['tx-max-download']);
35
  update_option('wplnst_user_agent', stripslashes($_POST['tx-user-agent']));
36
-
37
  // Timeouts update
38
  update_option('wplnst_connect_timeout', (int) $_POST['tx-connect-timeout']);
39
  update_option('wplnst_request_timeout', (int) $_POST['tx-request-timeout']);
@@ -43,19 +44,19 @@ class WPLNST_Admin_Settings {
43
  update_option('wplnst_summary_status', (int) $_POST['tx-summary-status']);
44
  update_option('wplnst_summary_phases', (int) $_POST['tx-summary-phases']);
45
  update_option('wplnst_summary_objects', (int) $_POST['tx-summary-objects']);
46
-
47
  // Advanced update
48
  update_option('wplnst_recursion_limit', (int) $_POST['tx-recursion-limit']);
49
  update_option('wplnst_mysql_calc_rows', empty($_POST['ck-mysql-calc-rows'])? 'off' : 'on');
50
  update_option('wplnst_uninstall_data', empty($_POST['ck-uninstall-data'])? 'off' : 'on');
51
-
52
  // Update notice
53
  $notice_success = __('Settings updated', 'wplnst');
54
  }
55
-
56
  // Custom action view
57
  add_action('wplnst_view_settings', array(&$this, 'view_settings'));
58
-
59
  // Show settings screen
60
  $admin->screen_view(array(
61
  'title' => WPLNST_Admin::get_text('settings'),
1
  <?php
2
 
3
  /**
4
+ * Admin Settings class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Admin
8
  */
9
  class WPLNST_Admin_Settings {
10
 
14
  * Constructor
15
  */
16
  public function __construct(&$admin) {
17
+
18
  // Initialize
19
  $notice_success = $notice_error = false;
20
+
21
  // Check submit
22
  if (isset($_POST['settings_nonce'])) {
23
+
24
  // Check nonce
25
+ if (!wp_verify_nonce($_POST['settings_nonce'], WPLNST_Core_Plugin::slug.'-settings')) {
26
  return $admin->screen_invalid_nonce(WPLNST_Admin::get_text('settings'));
27
+ }
28
+
29
  // General update
30
  update_option('wplnst_max_threads', (int) $_POST['tx-max-threads']);
31
  update_option('wplnst_max_scans', (int) $_POST['tx-max-scans']);
34
  update_option('wplnst_max_redirs', (int) $_POST['tx-max-redirs']);
35
  update_option('wplnst_max_download', (int) $_POST['tx-max-download']);
36
  update_option('wplnst_user_agent', stripslashes($_POST['tx-user-agent']));
37
+
38
  // Timeouts update
39
  update_option('wplnst_connect_timeout', (int) $_POST['tx-connect-timeout']);
40
  update_option('wplnst_request_timeout', (int) $_POST['tx-request-timeout']);
44
  update_option('wplnst_summary_status', (int) $_POST['tx-summary-status']);
45
  update_option('wplnst_summary_phases', (int) $_POST['tx-summary-phases']);
46
  update_option('wplnst_summary_objects', (int) $_POST['tx-summary-objects']);
47
+
48
  // Advanced update
49
  update_option('wplnst_recursion_limit', (int) $_POST['tx-recursion-limit']);
50
  update_option('wplnst_mysql_calc_rows', empty($_POST['ck-mysql-calc-rows'])? 'off' : 'on');
51
  update_option('wplnst_uninstall_data', empty($_POST['ck-uninstall-data'])? 'off' : 'on');
52
+
53
  // Update notice
54
  $notice_success = __('Settings updated', 'wplnst');
55
  }
56
+
57
  // Custom action view
58
  add_action('wplnst_view_settings', array(&$this, 'view_settings'));
59
+
60
  // Show settings screen
61
  $admin->screen_view(array(
62
  'title' => WPLNST_Admin::get_text('settings'),
assets/css/admin.css CHANGED
@@ -12,19 +12,19 @@
12
  .wplnst-tab {
13
  display: none;
14
  }
15
-
16
  #wplnst-tabs.wplnst-tabs-scan-edit .wplnst-tab .form-table th {
17
  width: 150px;
18
  }
19
-
20
  .wplnst-tab .form-table td {
21
  vertical-align: top;
22
  }
23
-
24
  .wplnst-tab .form-table td.wplnst-list {
25
  line-height: 1.9em;
26
  }
27
-
28
  .wplnst-tab .form-table td.wplnst-value {
29
  padding-top: 20px;
30
  line-height: 1.3em;
@@ -34,7 +34,7 @@
34
  padding-top: 15px;
35
  line-height: 1.9em;
36
  }
37
-
38
  .wplnst-tab-active {
39
  display: block;
40
  }
@@ -42,54 +42,54 @@
42
  #wplnst-destination-type, #wplnst-time-scope, #wplnst-crawl-order {
43
  width: 185px;
44
  }
45
-
46
  #wplnst-cf-new {
47
  width: 215px;
48
  }
49
-
50
  a.wplnst-trash-editor, a.wplnst-trash-editor:hover {
51
  color: #a00;
52
  }
53
-
54
  .wplnst-elist {
55
  border: 0; display: none;
56
  margin: 0 0 5px; padding: 0;
57
  }
58
-
59
  .wplnst-elist-visible { display: block; }
60
  .wplnst-elist-readonly { margin: 0; }
61
-
62
  .wplnst-elist tr {
63
  margin-bottom: 10px;
64
  }
65
-
66
  .wplnst-elist tr td {
67
- margin: 0; padding: 4px 5px;
68
  }
69
-
70
  .wplnst-elist tr td.wplnst-elist-val {
71
  color: #5c5a5a;
72
  background: #f9f9f9;
73
  }
74
-
75
  #wplnst-af-new { width: 361px; }
76
  #wplnst-ius-new { width: 425px; }
77
  #wplnst-eus-new { width: 425px; }
78
-
79
  .wplnst-elist tr td.wplnst-cfs-val { width: 205px; }
80
  .wplnst-elist tr td.wplnst-afs-val { width: 350px; }
81
  .wplnst-elist tr td.wplnst-ius-val { width: 415px; }
82
  .wplnst-elist tr td.wplnst-eus-val { width: 415px; }
83
-
84
  .wplnst-elist tr td.wplnst-elist-type {
85
  color: #6f6f6f;
86
  }
87
-
88
  .wplnst-elist tr td.wplnst-cfs-type { width: 53px; padding-left: 12px; }
89
  .wplnst-elist tr td.wplnst-afs-type { width: 200px; padding-left: 0; }
90
  .wplnst-elist tr td.wplnst-ius-type { width: 121px; padding-left: 14px; }
91
  .wplnst-elist tr td.wplnst-eus-type { width: 121px; padding-left: 14px; }
92
-
93
  .wplnst-elist tr td.wplnst-hes-ele { width: 55px; font-weight: bold; }
94
  .wplnst-elist tr td.wplnst-hes-have { width: 87px; font-weight: bold; }
95
  .wplnst-elist tr td.wplnst-hes-att { width: 125px; }
@@ -99,9 +99,9 @@
99
  .wplnst-elist tr td.wplnst-elist-close {
100
  padding-left: 21px;
101
  }
102
-
103
  /* .wplnst-elist tr td.wplnst-afs-close { padding-left: 20px; } */
104
-
105
  .wplnst-elist tr td.wplnst-elist-close .wplnst-elist-close-link {
106
  display: block;
107
  width: 16px; height: 16px;
@@ -109,11 +109,11 @@
109
  text-indent: -9999px;
110
  background: url(../images/button-close.png) left top no-repeat;
111
  }
112
-
113
  .wplnst-elist tr td.wplnst-elist-close .wplnst-elist-close-link:hover {
114
  background: url(../images/button-close-hover.png) left top no-repeat;
115
  }
116
-
117
  .wplnst-elist tr td.wplnst-elist-split {
118
  height: 3px;
119
  }
@@ -155,7 +155,7 @@ strong.wplnst-scan-name {
155
  color: #fff;
156
  background: #7b7d7b;
157
  }
158
-
159
  .wplnst-scan-status-stop {
160
  color: #fff;
161
  background: #383838;
@@ -170,11 +170,11 @@ strong.wplnst-scan-name {
170
  color: #fff;
171
  background: #5e9b1c;
172
  }
173
-
174
  .wplnst-scan-status-line {
175
  margin: 0 0 10px 1px;
176
  }
177
-
178
  .wplnst-scan-object-info {
179
  color: #848585;
180
  background: #e5e5e5;
@@ -185,23 +185,23 @@ strong.wplnst-scan-name {
185
  border-radius: 2px;
186
  -khtml-border-radius: 2px;
187
  }
188
-
189
  .wplnst-scan-object-running {
190
  color: #56524e;
191
  }
192
 
193
- .wplnst-scan-object-wait {
194
  background: #f2f2f2;
195
  }
196
 
197
  .wplnst-scan-object-completed {
198
- color: #32373c;
199
  }
200
-
201
  .wplnst-scan-object-completed-end {
202
  color: #5e6455;
203
  }
204
-
205
  .wplnst-scan-name-warning img {
206
  padding-top: 2px;
207
  }
@@ -211,31 +211,31 @@ strong.wplnst-scan-name {
211
  padding: 0 0 0 23px;
212
  background: url(../images/scan-launch.png) left 1px no-repeat;
213
  }
214
-
215
  .wplnst-scan-ready-info a {
216
  font-weight: bold;
217
  }
218
-
219
  .wplnst-scan-time-info {
220
  margin: 0 0 7px 1px;
221
  padding: 0 0 0 23px;
222
  background: url(../images/scan-clock.png) left 2px no-repeat;
223
  }
224
-
225
  .wplnst-scan-links-info {
226
  margin: 0 0 7px 1px;
227
  padding: 0 0 0 23px;
228
  background: url(../images/scan-link.png) left 1px no-repeat;
229
  }
230
-
231
  .wplnst-scan-links-info strong {
232
  color: #4b4b4b;
233
  }
234
-
235
  .wplnst-scan-time-info, .wplnst-scan-links-info {
236
  color: #6f6f6f;
237
  }
238
-
239
  .wplnst-split-char {
240
  color: #a5a5a5;
241
  margin: 0 5px;
@@ -259,7 +259,7 @@ strong.wplnst-scan-name {
259
  /* Columns scan */
260
 
261
  .column-wplnst-scans-name {
262
- width: 40%;
263
  }
264
 
265
  .widefat td.column-wplnst-scans-name { padding-bottom: 15px; }
@@ -274,7 +274,7 @@ strong.wplnst-scan-name {
274
  .column-wplnst-scans-configuration table td, .widefat td.column-wplnst-scans-configuration table td {
275
  margin: 0; padding: 0 0 8px 0;
276
  }
277
-
278
  .column-wplnst-scans-configuration table td.wplnst-scans-configuration-row, .widefat td.column-wplnst-scans-configuration table td.wplnst-scans-configuration-row {
279
  width: 100px;
280
  }
@@ -311,11 +311,11 @@ strong.wplnst-scan-name {
311
  .wplnst-url-status-code {
312
  margin-bottom: 2px;
313
  }
314
-
315
  .wplnst-url-status-code-result {
316
  font-weight: bold;
317
  }
318
-
319
  .wplnst-url-status-code-0 {
320
  color: black;
321
  }
@@ -331,20 +331,20 @@ strong.wplnst-scan-name {
331
  .wplnst-url-status-code-4 {
332
  color: red;
333
  }
334
-
335
  .wplnst-url-status-code-redir {
336
  font-weight: bold;
337
  }
338
-
339
  .wplnst-url-status-code-redir-arrow {
340
  font-weight: normal;
341
  }
342
-
343
  .wplnst-url-status-info {
344
  color: #7a7a7a;
345
  margin-bottom: 2px;
346
  }
347
-
348
  .wplnst-url-status-info-split {
349
  color: #ccc;
350
  vertical-align: top;
@@ -366,11 +366,11 @@ strong.wplnst-scan-name {
366
  .wplnst-row-dashicon {
367
  margin-bottom: 5px;
368
  }
369
-
370
  .wplnst-row-dashicon span {
371
  padding-left: 2px;
372
  }
373
-
374
  .wplnst-row-dashicon:before {
375
  font-family: "dashicons";
376
  padding-right: 3px;
@@ -381,11 +381,11 @@ strong.wplnst-scan-name {
381
  .wplnst-content-post:before {
382
  content: "\f109";
383
  }
384
-
385
  .wplnst-content-comment:before {
386
  content: "\f101";
387
  }
388
-
389
  .wplnst-content-bookmark:before {
390
  content: "\f103";
391
  }
@@ -422,7 +422,7 @@ strong.wplnst-scan-name {
422
  background: #8f9779;
423
  border-color: #8f9779;
424
  }
425
-
426
  .wplnst-results-mark-modified {
427
  background: #dd855c;
428
  border-color: #dd855c;
@@ -432,42 +432,42 @@ strong.wplnst-scan-name {
432
  background: #f96161;
433
  border-color: #f96161;
434
  }
435
-
436
  .wplnst-results-mark-relative {
437
  background: #ff99cc;
438
  border-color: #ff99cc;
439
  }
440
-
441
  .wplnst-results-mark-absolute {
442
  background: #ff77aa;
443
  border-color: #ff77aa;
444
  }
445
-
446
  .wplnst-results-mark-spaced {
447
  background: #e1c348;
448
  border-color: #e1c348;
449
  }
450
-
451
  .wplnst-results-mark-malformed {
452
  background: #fe0000;
453
  border-color: #fe0000;
454
  }
455
-
456
  .wplnst-results-mark-https {
457
  background: #b5bc67;
458
  border-color: #b5bc67;
459
  }
460
-
461
  .wplnst-results-mark-protorel {
462
  background: #662f44;
463
  border-color: #662f44;
464
  }
465
-
466
  .wplnst-results-mark-ignored {
467
  background: #afbec0;
468
  border-color: #afbec0;
469
  }
470
-
471
  .wplnst-results-mark-redirs {
472
  background: #69b2ac;
473
  border-color: #69b2ac;
@@ -504,10 +504,10 @@ strong.wplnst-scan-name {
504
  #wplnst-levels-menu .subsubsub {
505
  margin: 0; padding: 0;
506
  }
507
-
508
  .wplnst-aproximate-total {
509
  color: #777;
510
- padding-top: 4px;
511
  }
512
 
513
 
@@ -521,16 +521,16 @@ strong.wplnst-scan-name {
521
  .wplnst-extensions-section {
522
  margin-bottom: 50px;
523
  }
524
-
525
  #wplnst-extensions h3 {
526
  font-size: 1.4em;
527
  letter-spacing: -1px;
528
  }
529
-
530
  #wplnst-extensions p {
531
  font-size: 1.3em;
532
  }
533
-
534
  #wplnst-extensions img {
535
  border: 1px solid #ccc;
536
  }
12
  .wplnst-tab {
13
  display: none;
14
  }
15
+
16
  #wplnst-tabs.wplnst-tabs-scan-edit .wplnst-tab .form-table th {
17
  width: 150px;
18
  }
19
+
20
  .wplnst-tab .form-table td {
21
  vertical-align: top;
22
  }
23
+
24
  .wplnst-tab .form-table td.wplnst-list {
25
  line-height: 1.9em;
26
  }
27
+
28
  .wplnst-tab .form-table td.wplnst-value {
29
  padding-top: 20px;
30
  line-height: 1.3em;
34
  padding-top: 15px;
35
  line-height: 1.9em;
36
  }
37
+
38
  .wplnst-tab-active {
39
  display: block;
40
  }
42
  #wplnst-destination-type, #wplnst-time-scope, #wplnst-crawl-order {
43
  width: 185px;
44
  }
45
+
46
  #wplnst-cf-new {
47
  width: 215px;
48
  }
49
+
50
  a.wplnst-trash-editor, a.wplnst-trash-editor:hover {
51
  color: #a00;
52
  }
53
+
54
  .wplnst-elist {
55
  border: 0; display: none;
56
  margin: 0 0 5px; padding: 0;
57
  }
58
+
59
  .wplnst-elist-visible { display: block; }
60
  .wplnst-elist-readonly { margin: 0; }
61
+
62
  .wplnst-elist tr {
63
  margin-bottom: 10px;
64
  }
65
+
66
  .wplnst-elist tr td {
67
+ margin: 0; padding: 4px 5px;
68
  }
69
+
70
  .wplnst-elist tr td.wplnst-elist-val {
71
  color: #5c5a5a;
72
  background: #f9f9f9;
73
  }
74
+
75
  #wplnst-af-new { width: 361px; }
76
  #wplnst-ius-new { width: 425px; }
77
  #wplnst-eus-new { width: 425px; }
78
+
79
  .wplnst-elist tr td.wplnst-cfs-val { width: 205px; }
80
  .wplnst-elist tr td.wplnst-afs-val { width: 350px; }
81
  .wplnst-elist tr td.wplnst-ius-val { width: 415px; }
82
  .wplnst-elist tr td.wplnst-eus-val { width: 415px; }
83
+
84
  .wplnst-elist tr td.wplnst-elist-type {
85
  color: #6f6f6f;
86
  }
87
+
88
  .wplnst-elist tr td.wplnst-cfs-type { width: 53px; padding-left: 12px; }
89
  .wplnst-elist tr td.wplnst-afs-type { width: 200px; padding-left: 0; }
90
  .wplnst-elist tr td.wplnst-ius-type { width: 121px; padding-left: 14px; }
91
  .wplnst-elist tr td.wplnst-eus-type { width: 121px; padding-left: 14px; }
92
+
93
  .wplnst-elist tr td.wplnst-hes-ele { width: 55px; font-weight: bold; }
94
  .wplnst-elist tr td.wplnst-hes-have { width: 87px; font-weight: bold; }
95
  .wplnst-elist tr td.wplnst-hes-att { width: 125px; }
99
  .wplnst-elist tr td.wplnst-elist-close {
100
  padding-left: 21px;
101
  }
102
+
103
  /* .wplnst-elist tr td.wplnst-afs-close { padding-left: 20px; } */
104
+
105
  .wplnst-elist tr td.wplnst-elist-close .wplnst-elist-close-link {
106
  display: block;
107
  width: 16px; height: 16px;
109
  text-indent: -9999px;
110
  background: url(../images/button-close.png) left top no-repeat;
111
  }
112
+
113
  .wplnst-elist tr td.wplnst-elist-close .wplnst-elist-close-link:hover {
114
  background: url(../images/button-close-hover.png) left top no-repeat;
115
  }
116
+
117
  .wplnst-elist tr td.wplnst-elist-split {
118
  height: 3px;
119
  }
155
  color: #fff;
156
  background: #7b7d7b;
157
  }
158
+
159
  .wplnst-scan-status-stop {
160
  color: #fff;
161
  background: #383838;
170
  color: #fff;
171
  background: #5e9b1c;
172
  }
173
+
174
  .wplnst-scan-status-line {
175
  margin: 0 0 10px 1px;
176
  }
177
+
178
  .wplnst-scan-object-info {
179
  color: #848585;
180
  background: #e5e5e5;
185
  border-radius: 2px;
186
  -khtml-border-radius: 2px;
187
  }
188
+
189
  .wplnst-scan-object-running {
190
  color: #56524e;
191
  }
192
 
193
+ .wplnst-scan-object-wait {
194
  background: #f2f2f2;
195
  }
196
 
197
  .wplnst-scan-object-completed {
198
+ color: #32373c;
199
  }
200
+
201
  .wplnst-scan-object-completed-end {
202
  color: #5e6455;
203
  }
204
+
205
  .wplnst-scan-name-warning img {
206
  padding-top: 2px;
207
  }
211
  padding: 0 0 0 23px;
212
  background: url(../images/scan-launch.png) left 1px no-repeat;
213
  }
214
+
215
  .wplnst-scan-ready-info a {
216
  font-weight: bold;
217
  }
218
+
219
  .wplnst-scan-time-info {
220
  margin: 0 0 7px 1px;
221
  padding: 0 0 0 23px;
222
  background: url(../images/scan-clock.png) left 2px no-repeat;
223
  }
224
+
225
  .wplnst-scan-links-info {
226
  margin: 0 0 7px 1px;
227
  padding: 0 0 0 23px;
228
  background: url(../images/scan-link.png) left 1px no-repeat;
229
  }
230
+
231
  .wplnst-scan-links-info strong {
232
  color: #4b4b4b;
233
  }
234
+
235
  .wplnst-scan-time-info, .wplnst-scan-links-info {
236
  color: #6f6f6f;
237
  }
238
+
239
  .wplnst-split-char {
240
  color: #a5a5a5;
241
  margin: 0 5px;
259
  /* Columns scan */
260
 
261
  .column-wplnst-scans-name {
262
+ width: 40%;
263
  }
264
 
265
  .widefat td.column-wplnst-scans-name { padding-bottom: 15px; }
274
  .column-wplnst-scans-configuration table td, .widefat td.column-wplnst-scans-configuration table td {
275
  margin: 0; padding: 0 0 8px 0;
276
  }
277
+
278
  .column-wplnst-scans-configuration table td.wplnst-scans-configuration-row, .widefat td.column-wplnst-scans-configuration table td.wplnst-scans-configuration-row {
279
  width: 100px;
280
  }
311
  .wplnst-url-status-code {
312
  margin-bottom: 2px;
313
  }
314
+
315
  .wplnst-url-status-code-result {
316
  font-weight: bold;
317
  }
318
+
319
  .wplnst-url-status-code-0 {
320
  color: black;
321
  }
331
  .wplnst-url-status-code-4 {
332
  color: red;
333
  }
334
+
335
  .wplnst-url-status-code-redir {
336
  font-weight: bold;
337
  }
338
+
339
  .wplnst-url-status-code-redir-arrow {
340
  font-weight: normal;
341
  }
342
+
343
  .wplnst-url-status-info {
344
  color: #7a7a7a;
345
  margin-bottom: 2px;
346
  }
347
+
348
  .wplnst-url-status-info-split {
349
  color: #ccc;
350
  vertical-align: top;
366
  .wplnst-row-dashicon {
367
  margin-bottom: 5px;
368
  }
369
+
370
  .wplnst-row-dashicon span {
371
  padding-left: 2px;
372
  }
373
+
374
  .wplnst-row-dashicon:before {
375
  font-family: "dashicons";
376
  padding-right: 3px;
381
  .wplnst-content-post:before {
382
  content: "\f109";
383
  }
384
+
385
  .wplnst-content-comment:before {
386
  content: "\f101";
387
  }
388
+
389
  .wplnst-content-bookmark:before {
390
  content: "\f103";
391
  }
422
  background: #8f9779;
423
  border-color: #8f9779;
424
  }
425
+
426
  .wplnst-results-mark-modified {
427
  background: #dd855c;
428
  border-color: #dd855c;
432
  background: #f96161;
433
  border-color: #f96161;
434
  }
435
+
436
  .wplnst-results-mark-relative {
437
  background: #ff99cc;
438
  border-color: #ff99cc;
439
  }
440
+
441
  .wplnst-results-mark-absolute {
442
  background: #ff77aa;
443
  border-color: #ff77aa;
444
  }
445
+
446
  .wplnst-results-mark-spaced {
447
  background: #e1c348;
448
  border-color: #e1c348;
449
  }
450
+
451
  .wplnst-results-mark-malformed {
452
  background: #fe0000;
453
  border-color: #fe0000;
454
  }
455
+
456
  .wplnst-results-mark-https {
457
  background: #b5bc67;
458
  border-color: #b5bc67;
459
  }
460
+
461
  .wplnst-results-mark-protorel {
462
  background: #662f44;
463
  border-color: #662f44;
464
  }
465
+
466
  .wplnst-results-mark-ignored {
467
  background: #afbec0;
468
  border-color: #afbec0;
469
  }
470
+
471
  .wplnst-results-mark-redirs {
472
  background: #69b2ac;
473
  border-color: #69b2ac;
504
  #wplnst-levels-menu .subsubsub {
505
  margin: 0; padding: 0;
506
  }
507
+
508
  .wplnst-aproximate-total {
509
  color: #777;
510
+ padding-top: 4px;
511
  }
512
 
513
 
521
  .wplnst-extensions-section {
522
  margin-bottom: 50px;
523
  }
524
+
525
  #wplnst-extensions h3 {
526
  font-size: 1.4em;
527
  letter-spacing: -1px;
528
  }
529
+
530
  #wplnst-extensions p {
531
  font-size: 1.3em;
532
  }
533
+
534
  #wplnst-extensions img {
535
  border: 1px solid #ccc;
536
  }
assets/icon.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+
3
+ return 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiICAgdmVyc2lvbj0iMS4xIiAgIHg9IjBweCIgICB5PSIwcHgiICAgdmlld0JveD0iMCAwIDEwMCAxMDAiICAgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTAwIDEwMCIgICB4bWw6c3BhY2U9InByZXNlcnZlIiAgIGlkPSJzdmcyIiAgIGlua3NjYXBlOnZlcnNpb249IjAuNDguNCByOTkzOSIgICB3aWR0aD0iMTAwJSIgICBoZWlnaHQ9IjEwMCUiICAgc29kaXBvZGk6ZG9jbmFtZT0ibGluay1zdGF0dXMtNy5zdmciPjxtZXRhZGF0YSAgICAgaWQ9Im1ldGFkYXRhMTAiPjxyZGY6UkRGPjxjYzpXb3JrICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcyAgICAgaWQ9ImRlZnM4IiAvPjxzb2RpcG9kaTpuYW1lZHZpZXcgICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIgICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IiAgICAgYm9yZGVyb3BhY2l0eT0iMSIgICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiICAgICBncmlkdG9sZXJhbmNlPSIxMCIgICAgIGd1aWRldG9sZXJhbmNlPSIxMCIgICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIgICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTY4MCIgICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9Ijk3NCIgICAgIGlkPSJuYW1lZHZpZXc2IiAgICAgc2hvd2dyaWQ9ImZhbHNlIiAgICAgaW5rc2NhcGU6em9vbT0iMi4zNiIgICAgIGlua3NjYXBlOmN4PSItMjguNjAxNjk1IiAgICAgaW5rc2NhcGU6Y3k9IjUwIiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjAiICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMjQiICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ic3ZnMiIgLz48cGF0aCAgICAgZD0iTTUwLDBDMjIuNCwwLDAsMjIuNCwwLDUwczIyLjQsNTAsNTAsNTBzNTAtMjIuNCw1MC01MFM3Ny42LDAsNTAsMHogTTU1LjgsNjUuM0w0NCw3N2MtMy4yLDMuMi03LjUsNS0xMS44LDVoMCAgYy0zLjksMC03LjUtMS41LTEwLjItNC4xYy01LjgtNS44LTUuOC0xNS4zLDAtMjEuMWwxNC4xLTE0LjFMMzYsNDQuOWMtMC4yLDIuNiwwLjEsNS4xLDAuOSw3LjRsMC4yLDAuNWwtOS41LDkuNSAgYy0xLjQsMS40LTIuMSwzLjItMi4xLDUuMWMwLDEuOSwwLjcsMy43LDIuMSw1LjFjMS4yLDEuMiwyLjksMS45LDQuNywxLjljMi4zLDAsNC42LTEsNi4zLTIuN2wxMS43LTExLjdjMy4zLTMuMywzLjctOC4yLDAuOS0xMSAgYy0wLjctMC43LTEtMS45LTAuOC0zLjFjMC4yLTEuMiwwLjgtMi4zLDEuNy0zLjJsMS41LTEuNWwwLjUsMC4zYzAuOSwwLjYsMS44LDEuMywyLjUsMmMwLjgsMC44LDEuNCwxLjYsMiwyLjYgIEM2Mi4zLDUxLjksNjEuMSw2MCw1NS44LDY1LjN6IE03Ny45LDQzLjJMNjMuOCw1Ny4zbDAuMi0yLjFjMC4yLTIuNi0wLjEtNS4xLTAuOS03LjRMNjMsNDcuMmw5LjUtOS41YzEuNC0xLjQsMi4xLTMuMiwyLjEtNS4xICBjMC0xLjktMC43LTMuNy0yLjEtNS4xYy0xLjItMS4yLTIuOS0xLjktNC43LTEuOWMtMi4zLDAtNC42LDEtNi4zLDIuN0w0OS43LDQwLjFjLTMuMywzLjMtMy43LDguMi0wLjksMTFjMC43LDAuNywxLDEuOSwwLjgsMy4xICBjLTAuMiwxLjItMC44LDIuMy0xLjcsMy4yTDQ2LjQsNTlsLTAuNS0wLjNjLTAuOS0wLjYtMS44LTEuMy0yLjUtMmMtMC44LTAuOC0xLjQtMS42LTItMi42Yy0zLjYtNS45LTIuNC0xNC4xLDIuOS0xOS40TDU2LDIzICBjMy4yLTMuMiw3LjUtNSwxMS44LTVjMy45LDAsNy41LDEuNSwxMC4yLDQuMWMyLjgsMi44LDQuNCw2LjYsNC40LDEwLjVDODIuMywzNi42LDgwLjcsNDAuNCw3Ny45LDQzLjJ6IiAgICAgaWQ9InBhdGg0IiAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZjtmaWxsLW9wYWNpdHk6MSIgLz48L3N2Zz4=';
assets/images/button-close-hover.png CHANGED
File without changes
assets/images/button-close.png CHANGED
File without changes
assets/images/loading.gif CHANGED
File without changes
assets/images/scan-warning.png CHANGED
File without changes
assets/images/yes.png CHANGED
File without changes
assets/js/admin-edit.js CHANGED
@@ -7,36 +7,41 @@
7
 
8
 
9
  function elist_arrange(names) {
10
-
11
  var rq = /\%quot\%/g;
12
  var n, name, field, editable, f;
13
-
14
  for (n in names) {
15
-
16
  name = names[n];
17
  field = $('#wplnst-scan-' + name).val();
18
  field = ('' === field)? [] : JSON.parse(field);
19
- if (!(field instanceof Array) || 0 == field.length)
20
  continue;
21
-
 
22
  elist_index[name] = field.length;
23
  editable = ('true' == $('#wplnst-elist-' + name).attr('data-editable'));
24
-
25
  if ('custom-fields' == name) {
26
- for (f in field)
27
  elist_add_row(name, elist_get_row(name, {'name' : field[f]['name'].esc_html().replace(rq, '&quot;'), 'type' : field[f]['type'].esc_html().toUpperCase()}, editable), field[f]['index']);
28
-
 
29
  } else if ('anchor-filters' == name) {
30
- for (f in field)
31
  elist_add_row(name, elist_get_row(name, {'value' : field[f]['value'].esc_html().replace(rq, '&quot;'), 'type' : field[f]['type'].esc_html().replace('-', ' ')}, editable), field[f]['index']);
32
-
 
33
  } else if ('include-urls' == name || 'exclude-urls' == name) {
34
- for (f in field)
35
  elist_add_row(name, elist_get_row(name, {'value' : field[f]['value'].esc_html().replace(rq, '&quot;'), 'type' : field[f]['type'].esc_html().replace('-', ' ').replace('url ', 'URL ').replace(' url', ' URL').capitalize()}, editable), field[f]['index']);
36
-
 
37
  } else if ('html-attributes' == name) {
38
- for (f in field)
39
  elist_add_row(name, elist_get_row('html-attributes', {'element' : field[f]['element'].esc_html(), 'having' : field[f]['having'].esc_html().replace('-', ' '), 'att' : field[f]['att'].esc_html().replace(rq, '&quot;'), 'op' : field[f]['op'].esc_html().replace('-', ' '), 'value' : field[f]['value'].esc_html().replace(rq, '&quot;')}, editable), field[f]['index']);
 
40
  }
41
  }
42
  }
@@ -44,21 +49,23 @@
44
 
45
 
46
  function elist_add(name, value, inputs, row) {
47
-
48
  var field = $('#wplnst-scan-' + name).val();
49
  field = ('' === field)? [] : JSON.parse(field);
50
- if (!(field instanceof Array) || field.length > 25)
51
  return;
52
-
 
53
  (name in elist_index)? elist_index[name]++ : elist_index[name] = 0;
54
  value['index'] = elist_index[name];
55
  field.push(value);
56
-
57
  $('#wplnst-scan-' + name).val(JSON.stringify(field));
58
 
59
- for (var i = 0; i < inputs.length; i++)
60
  $('#' + inputs[i]).val('');
61
-
 
62
  elist_add_row(name, row, value['index']);
63
  }
64
 
@@ -74,22 +81,27 @@
74
 
75
 
76
  function elist_get_row(name, args, editable) {
77
-
78
- if ('custom-fields' == name)
79
  return '<tr class="%class-index%"><td class="wplnst-elist-val wplnst-cfs-val">' + args['name'] + '</td><td class="wplnst-elist-type wplnst-cfs-type">' + args['type'] + '</td><td class="wplnst-elist-close">' + (editable? '%close%' : '') + '</td></tr><tr class="%class-index%"><td colspan="3" class="wplnst-elist-split"></td></tr>';
80
-
81
- if ('anchor-filters' == name)
 
82
  return '<tr class="%class-index%"><td class="wplnst-elist-type wplnst-afs-type">' + $('#wplnst-elist-anchor-filters').attr('data-label') + '&nbsp; <strong>' + args['type'] + '</strong></td><td class="wplnst-elist-val wplnst-afs-val">' + args['value'] + '</td><td class="wplnst-elist-close wplnst-afs-close">' + (editable? '%close%' : '') + '</td></tr><tr class="%class-index%"><td colspan="3" class="wplnst-elist-split"></td></tr>';
83
-
84
- if ('include-urls' == name)
 
85
  return '<tr class="%class-index%"><td class="wplnst-elist-val wplnst-ius-val">' + args['value'] + '</td><td class="wplnst-elist-type wplnst-ius-type">' + args['type'] + '</td><td class="wplnst-elist-close">' + (editable? '%close%' : '') + '</td></tr><tr class="%class-index%"><td colspan="3" class="wplnst-elist-split"></td></tr>';
86
-
87
- if ('exclude-urls' == name)
 
88
  return '<tr class="%class-index%"><td class="wplnst-elist-val wplnst-eus-val">' + args['value'] + '</td><td class="wplnst-elist-type wplnst-eus-type">' + args['type'] + '</td><td class="wplnst-elist-close">' + (editable? '%close%' : '') + '</td></tr><tr class="%class-index%"><td colspan="3" class="wplnst-elist-split"></td></tr>';
89
-
90
- if ('html-attributes' == name)
 
91
  return '<tr class="%class-index%"><td class="wplnst-elist-type wplnst-hes-ele">' + args['element'] + '</td><td class="wplnst-elist-type wplnst-hes-have">' + args['having'] + '</td><td class="wplnst-elist-val wplnst-hes-att">' + args['att'] + '</td><td class="wplnst-elist-type wplnst-hes-op">' + args['op'] + '</td><td class="wplnst-elist-val wplnst-hes-val">' + args['value'] + '</td><td class="wplnst-elist-close">' + (editable? '%close%' : '') + '</td></tr><tr class="%class-index%"><td colspan="3" class="wplnst-elist-split"></td></tr>';
92
-
 
93
  return false;
94
  }
95
 
@@ -98,27 +110,29 @@
98
 
99
  var name = $(this).attr('data-name');
100
  var index = $(this).attr('data-index');
101
-
102
  var field = $('#wplnst-scan-' + name).val();
103
  if ('' !== field) {
104
-
105
  field = JSON.parse(field);
106
  if (field instanceof Array) {
107
-
108
  var field_new = [];
109
  for (var i = 0; i < field.length; i++) {
110
- if (index != field[i]['index'])
111
  field_new.push(field[i]);
 
112
  }
113
-
114
  $('#wplnst-scan-' + name).val(JSON.stringify(field_new));
115
  $('.wplnst-' + name + '-' + index).remove();
116
-
117
- if (0 === field_new.length)
118
  $('#' + 'wplnst-elist-' + name).hide();
 
119
  }
120
  }
121
-
122
  return false;
123
  });
124
 
@@ -145,11 +159,12 @@
145
 
146
  $('#wplnst-cf-new-add').click(function() {
147
  var name = $('#wplnst-cf-new').val().trim();
148
- if ('' === name)
149
  return;
 
150
  elist_add('custom-fields', {'name' : name, 'type': $('#wplnst-cf-new-type').val()}, ['wplnst-cf-new'], elist_get_row('custom-fields', {'name' : name.esc_html(), 'type' : $('#wplnst-cf-new-type option:selected').text().esc_html()}, true));
151
  });
152
-
153
  $('#wplnst-cf-new').bind('keypress', function(e) {
154
  if (e.keyCode == 13) {
155
  $('#wplnst-cf-new-add').click();
@@ -162,8 +177,9 @@
162
  $('#wplnst-af-new-add').click(function() {
163
  var value = $('#wplnst-af-new').val().trim();
164
  var type = $('#wplnst-af-new-type').val();
165
- if ('' === value && 'empty' != type)
166
  return;
 
167
  elist_add('anchor-filters', {'value' : ('empty' != type)? value : '', 'type': type}, ['wplnst-af-new'], elist_get_row('anchor-filters', {'type' : $('#wplnst-af-new-type option:selected').text().esc_html().toLowerCase(), 'value' : ('empty' != type)? value.esc_html() : ''}, true));
168
  });
169
 
@@ -183,8 +199,9 @@
183
 
184
  $('#wplnst-ius-new-add').click(function() {
185
  var value = $('#wplnst-ius-new').val().trim();
186
- if ('' === value)
187
  return;
 
188
  elist_add('include-urls', {'value' : value, 'type': $('#wplnst-ius-new-type').val()}, ['wplnst-ius-new'], elist_get_row('include-urls', {'value' : value.esc_html(), 'type' : $('#wplnst-ius-new-type option:selected').text().esc_html()}, true));
189
  });
190
 
@@ -199,8 +216,9 @@
199
 
200
  $('#wplnst-eus-new-add').click(function() {
201
  var value = $('#wplnst-eus-new').val().trim();
202
- if ('' === value)
203
  return;
 
204
  elist_add('exclude-urls', {'value' : value, 'type': $('#wplnst-eus-new-type').val()}, ['wplnst-eus-new'], elist_get_row('exclude-urls', {'value' : value.esc_html(), 'type' : $('#wplnst-eus-new-type option:selected').text().esc_html()}, true));
205
  });
206
 
@@ -214,28 +232,29 @@
214
 
215
 
216
  $('#wplnst-hes-new-add').click(function() {
217
-
218
  var att = $('#wplnst-hes-new-att').val().trim();
219
- if ('' === att)
220
  return;
221
-
222
- var element = $('#wplnst-hes-new').val();
 
223
  var having = $('#wplnst-hes-new-have').val();
224
-
225
  var op = op_text = value = '';
226
  if ('have' == having) {
227
-
228
  var op = $('#wplnst-hes-new-op').val();
229
  var op_text = $('#wplnst-hes-new-op option:selected').text().toLowerCase();
230
  var value = '' + $('#wplnst-hes-new-val').val().trim();
231
-
232
  if ('not-empty' == op || 'empty' == op) {
233
  value = '';
234
  } else if ('' === value) {
235
  return;
236
  }
237
  }
238
-
239
  elist_add(
240
  'html-attributes',
241
  {'att' : att, 'element' : element, 'having' : having, 'op' : op, 'value' : value},
@@ -273,5 +292,5 @@
273
  elist_arrange(['custom-fields', 'anchor-filters', 'include-urls', 'exclude-urls', 'html-attributes']);
274
 
275
 
276
-
277
  });
7
 
8
 
9
  function elist_arrange(names) {
10
+
11
  var rq = /\%quot\%/g;
12
  var n, name, field, editable, f;
13
+
14
  for (n in names) {
15
+
16
  name = names[n];
17
  field = $('#wplnst-scan-' + name).val();
18
  field = ('' === field)? [] : JSON.parse(field);
19
+ if (!(field instanceof Array) || 0 == field.length) {
20
  continue;
21
+ }
22
+
23
  elist_index[name] = field.length;
24
  editable = ('true' == $('#wplnst-elist-' + name).attr('data-editable'));
25
+
26
  if ('custom-fields' == name) {
27
+ for (f in field) {
28
  elist_add_row(name, elist_get_row(name, {'name' : field[f]['name'].esc_html().replace(rq, '&quot;'), 'type' : field[f]['type'].esc_html().toUpperCase()}, editable), field[f]['index']);
29
+ }
30
+
31
  } else if ('anchor-filters' == name) {
32
+ for (f in field) {
33
  elist_add_row(name, elist_get_row(name, {'value' : field[f]['value'].esc_html().replace(rq, '&quot;'), 'type' : field[f]['type'].esc_html().replace('-', ' ')}, editable), field[f]['index']);
34
+ }
35
+
36
  } else if ('include-urls' == name || 'exclude-urls' == name) {
37
+ for (f in field) {
38
  elist_add_row(name, elist_get_row(name, {'value' : field[f]['value'].esc_html().replace(rq, '&quot;'), 'type' : field[f]['type'].esc_html().replace('-', ' ').replace('url ', 'URL ').replace(' url', ' URL').capitalize()}, editable), field[f]['index']);
39
+ }
40
+
41
  } else if ('html-attributes' == name) {
42
+ for (f in field) {
43
  elist_add_row(name, elist_get_row('html-attributes', {'element' : field[f]['element'].esc_html(), 'having' : field[f]['having'].esc_html().replace('-', ' '), 'att' : field[f]['att'].esc_html().replace(rq, '&quot;'), 'op' : field[f]['op'].esc_html().replace('-', ' '), 'value' : field[f]['value'].esc_html().replace(rq, '&quot;')}, editable), field[f]['index']);
44
+ }
45
  }
46
  }
47
  }
49
 
50
 
51
  function elist_add(name, value, inputs, row) {
52
+
53
  var field = $('#wplnst-scan-' + name).val();
54
  field = ('' === field)? [] : JSON.parse(field);
55
+ if (!(field instanceof Array) || field.length > 25) {
56
  return;
57
+ }
58
+
59
  (name in elist_index)? elist_index[name]++ : elist_index[name] = 0;
60
  value['index'] = elist_index[name];
61
  field.push(value);
62
+
63
  $('#wplnst-scan-' + name).val(JSON.stringify(field));
64
 
65
+ for (var i = 0; i < inputs.length; i++) {
66
  $('#' + inputs[i]).val('');
67
+ }
68
+
69
  elist_add_row(name, row, value['index']);
70
  }
71
 
81
 
82
 
83
  function elist_get_row(name, args, editable) {
84
+
85
+ if ('custom-fields' == name) {
86
  return '<tr class="%class-index%"><td class="wplnst-elist-val wplnst-cfs-val">' + args['name'] + '</td><td class="wplnst-elist-type wplnst-cfs-type">' + args['type'] + '</td><td class="wplnst-elist-close">' + (editable? '%close%' : '') + '</td></tr><tr class="%class-index%"><td colspan="3" class="wplnst-elist-split"></td></tr>';
87
+ }
88
+
89
+ if ('anchor-filters' == name) {
90
  return '<tr class="%class-index%"><td class="wplnst-elist-type wplnst-afs-type">' + $('#wplnst-elist-anchor-filters').attr('data-label') + '&nbsp; <strong>' + args['type'] + '</strong></td><td class="wplnst-elist-val wplnst-afs-val">' + args['value'] + '</td><td class="wplnst-elist-close wplnst-afs-close">' + (editable? '%close%' : '') + '</td></tr><tr class="%class-index%"><td colspan="3" class="wplnst-elist-split"></td></tr>';
91
+ }
92
+
93
+ if ('include-urls' == name) {
94
  return '<tr class="%class-index%"><td class="wplnst-elist-val wplnst-ius-val">' + args['value'] + '</td><td class="wplnst-elist-type wplnst-ius-type">' + args['type'] + '</td><td class="wplnst-elist-close">' + (editable? '%close%' : '') + '</td></tr><tr class="%class-index%"><td colspan="3" class="wplnst-elist-split"></td></tr>';
95
+ }
96
+
97
+ if ('exclude-urls' == name) {
98
  return '<tr class="%class-index%"><td class="wplnst-elist-val wplnst-eus-val">' + args['value'] + '</td><td class="wplnst-elist-type wplnst-eus-type">' + args['type'] + '</td><td class="wplnst-elist-close">' + (editable? '%close%' : '') + '</td></tr><tr class="%class-index%"><td colspan="3" class="wplnst-elist-split"></td></tr>';
99
+ }
100
+
101
+ if ('html-attributes' == name) {
102
  return '<tr class="%class-index%"><td class="wplnst-elist-type wplnst-hes-ele">' + args['element'] + '</td><td class="wplnst-elist-type wplnst-hes-have">' + args['having'] + '</td><td class="wplnst-elist-val wplnst-hes-att">' + args['att'] + '</td><td class="wplnst-elist-type wplnst-hes-op">' + args['op'] + '</td><td class="wplnst-elist-val wplnst-hes-val">' + args['value'] + '</td><td class="wplnst-elist-close">' + (editable? '%close%' : '') + '</td></tr><tr class="%class-index%"><td colspan="3" class="wplnst-elist-split"></td></tr>';
103
+ }
104
+
105
  return false;
106
  }
107
 
110
 
111
  var name = $(this).attr('data-name');
112
  var index = $(this).attr('data-index');
113
+
114
  var field = $('#wplnst-scan-' + name).val();
115
  if ('' !== field) {
116
+
117
  field = JSON.parse(field);
118
  if (field instanceof Array) {
119
+
120
  var field_new = [];
121
  for (var i = 0; i < field.length; i++) {
122
+ if (index != field[i]['index']) {
123
  field_new.push(field[i]);
124
+ }
125
  }
126
+
127
  $('#wplnst-scan-' + name).val(JSON.stringify(field_new));
128
  $('.wplnst-' + name + '-' + index).remove();
129
+
130
+ if (0 === field_new.length) {
131
  $('#' + 'wplnst-elist-' + name).hide();
132
+ }
133
  }
134
  }
135
+
136
  return false;
137
  });
138
 
159
 
160
  $('#wplnst-cf-new-add').click(function() {
161
  var name = $('#wplnst-cf-new').val().trim();
162
+ if ('' === name) {
163
  return;
164
+ }
165
  elist_add('custom-fields', {'name' : name, 'type': $('#wplnst-cf-new-type').val()}, ['wplnst-cf-new'], elist_get_row('custom-fields', {'name' : name.esc_html(), 'type' : $('#wplnst-cf-new-type option:selected').text().esc_html()}, true));
166
  });
167
+
168
  $('#wplnst-cf-new').bind('keypress', function(e) {
169
  if (e.keyCode == 13) {
170
  $('#wplnst-cf-new-add').click();
177
  $('#wplnst-af-new-add').click(function() {
178
  var value = $('#wplnst-af-new').val().trim();
179
  var type = $('#wplnst-af-new-type').val();
180
+ if ('' === value && 'empty' != type) {
181
  return;
182
+ }
183
  elist_add('anchor-filters', {'value' : ('empty' != type)? value : '', 'type': type}, ['wplnst-af-new'], elist_get_row('anchor-filters', {'type' : $('#wplnst-af-new-type option:selected').text().esc_html().toLowerCase(), 'value' : ('empty' != type)? value.esc_html() : ''}, true));
184
  });
185
 
199
 
200
  $('#wplnst-ius-new-add').click(function() {
201
  var value = $('#wplnst-ius-new').val().trim();
202
+ if ('' === value) {
203
  return;
204
+ }
205
  elist_add('include-urls', {'value' : value, 'type': $('#wplnst-ius-new-type').val()}, ['wplnst-ius-new'], elist_get_row('include-urls', {'value' : value.esc_html(), 'type' : $('#wplnst-ius-new-type option:selected').text().esc_html()}, true));
206
  });
207
 
216
 
217
  $('#wplnst-eus-new-add').click(function() {
218
  var value = $('#wplnst-eus-new').val().trim();
219
+ if ('' === value) {
220
  return;
221
+ }
222
  elist_add('exclude-urls', {'value' : value, 'type': $('#wplnst-eus-new-type').val()}, ['wplnst-eus-new'], elist_get_row('exclude-urls', {'value' : value.esc_html(), 'type' : $('#wplnst-eus-new-type option:selected').text().esc_html()}, true));
223
  });
224
 
232
 
233
 
234
  $('#wplnst-hes-new-add').click(function() {
235
+
236
  var att = $('#wplnst-hes-new-att').val().trim();
237
+ if ('' === att) {
238
  return;
239
+ }
240
+
241
+ var element = $('#wplnst-hes-new').val();
242
  var having = $('#wplnst-hes-new-have').val();
243
+
244
  var op = op_text = value = '';
245
  if ('have' == having) {
246
+
247
  var op = $('#wplnst-hes-new-op').val();
248
  var op_text = $('#wplnst-hes-new-op option:selected').text().toLowerCase();
249
  var value = '' + $('#wplnst-hes-new-val').val().trim();
250
+
251
  if ('not-empty' == op || 'empty' == op) {
252
  value = '';
253
  } else if ('' === value) {
254
  return;
255
  }
256
  }
257
+
258
  elist_add(
259
  'html-attributes',
260
  {'att' : att, 'element' : element, 'having' : having, 'op' : op, 'value' : value},
292
  elist_arrange(['custom-fields', 'anchor-filters', 'include-urls', 'exclude-urls', 'html-attributes']);
293
 
294
 
295
+
296
  });
assets/js/admin.js CHANGED
@@ -36,18 +36,20 @@ jQuery(document).ready(function($) {
36
  var action = $('#wplnst-form').attr('action').split('#top#');
37
  $('#wplnst-form').attr('action', action[0] + '#top#' + id);
38
  });
39
-
40
  if ($('.wplnst-tab-default').length) {
41
- var active_tab = window.location.hash.replace('#top', '').replace('#wplnst-', '');
42
- if ('' === active_tab || active_tab === '#_=_')
43
  active_tab = $('.wplnst-tab-default').attr('id').replace('wplnst-', '');
 
44
  $('#wplnst-' + active_tab).addClass('wplnst-tab-active');
45
  $('#wplnst-' + active_tab + '-tab').addClass('nav-tab-active');
46
  $('#wplnst-' + active_tab + '-tab').click();
47
- if ('general' == active_tab && 0 == $('#wplnst-scan-id').val())
48
  $('#tx-name').focus();
 
49
  }
50
-
51
  $('.wplnst-scan-delete').click(function() {
52
  if (confirm($('#wplnst-scans').attr('data-confirm-delete'))) {
53
  $(this).attr('href', $(this).attr('href') + '&confirm=on');
@@ -73,7 +75,7 @@ jQuery(document).ready(function($) {
73
  $('.wplnst-remove-comment').click(function() {
74
  return confirm($('#wplnst-results').attr('data-confirm-delete-comment'));
75
  });
76
-
77
  $('.wplnst-remove-bookmark').click(function() {
78
  return confirm($('#wplnst-results').attr('data-confirm-delete-bookmark'));
79
  });
@@ -85,38 +87,41 @@ jQuery(document).ready(function($) {
85
  scans_bulkactions($('#bulk-action-selector-top').val());
86
  return false;
87
  });
88
-
89
  $('.wplnst-scans-bulkactions-bottom .button.action').click(function() {
90
  scans_bulkactions($('#bulk-action-selector-bottom').val());
91
  return false;
92
  });
93
-
94
  function scans_bulkactions(action) {
95
-
96
  if ('delete' == action) {
97
-
98
  var checked = [];
99
  $('input[type=checkbox].wplnst-ck-scan-id').each(function() {
100
- if ($(this).is(':checked'))
101
  checked.push($(this).val());
 
102
  });
103
-
104
  if (checked.length > 0) {
105
- if (confirm($('#wplnst-scans').attr('data-confirm-delete-bulk')))
106
  window.location.href = $('#wplnst-scans').attr('data-href-delete').replace('%scan_id%', '-' + checked.join('-')) + '&confirm=on';
 
107
  }
108
  }
109
  }
110
-
111
-
112
-
113
  $('#wplnst-filter-button').click(function() {
114
  var args = '', value;
115
  var fields = $(this).attr('data-fields').split(',');
116
  for (var i in fields) {
117
  value = $('#wplnst-filter-' + fields[i]).val();
118
- if (typeof value != 'undefined' && '' !== value)
119
  args += '&' + fields[i] + '=' + value;
 
120
  }
121
  window.location.href = $(this).attr('data-href') + args;
122
  return false;
36
  var action = $('#wplnst-form').attr('action').split('#top#');
37
  $('#wplnst-form').attr('action', action[0] + '#top#' + id);
38
  });
39
+
40
  if ($('.wplnst-tab-default').length) {
41
+ var active_tab = window.location.hash.replace('#top', '').replace('#wplnst-', '');
42
+ if ('' === active_tab || active_tab === '#_=_') {
43
  active_tab = $('.wplnst-tab-default').attr('id').replace('wplnst-', '');
44
+ }
45
  $('#wplnst-' + active_tab).addClass('wplnst-tab-active');
46
  $('#wplnst-' + active_tab + '-tab').addClass('nav-tab-active');
47
  $('#wplnst-' + active_tab + '-tab').click();
48
+ if ('general' == active_tab && 0 == $('#wplnst-scan-id').val()) {
49
  $('#tx-name').focus();
50
+ }
51
  }
52
+
53
  $('.wplnst-scan-delete').click(function() {
54
  if (confirm($('#wplnst-scans').attr('data-confirm-delete'))) {
55
  $(this).attr('href', $(this).attr('href') + '&confirm=on');
75
  $('.wplnst-remove-comment').click(function() {
76
  return confirm($('#wplnst-results').attr('data-confirm-delete-comment'));
77
  });
78
+
79
  $('.wplnst-remove-bookmark').click(function() {
80
  return confirm($('#wplnst-results').attr('data-confirm-delete-bookmark'));
81
  });
87
  scans_bulkactions($('#bulk-action-selector-top').val());
88
  return false;
89
  });
90
+
91
  $('.wplnst-scans-bulkactions-bottom .button.action').click(function() {
92
  scans_bulkactions($('#bulk-action-selector-bottom').val());
93
  return false;
94
  });
95
+
96
  function scans_bulkactions(action) {
97
+
98
  if ('delete' == action) {
99
+
100
  var checked = [];
101
  $('input[type=checkbox].wplnst-ck-scan-id').each(function() {
102
+ if ($(this).is(':checked')) {
103
  checked.push($(this).val());
104
+ }
105
  });
106
+
107
  if (checked.length > 0) {
108
+ if (confirm($('#wplnst-scans').attr('data-confirm-delete-bulk'))) {
109
  window.location.href = $('#wplnst-scans').attr('data-href-delete').replace('%scan_id%', '-' + checked.join('-')) + '&confirm=on';
110
+ }
111
  }
112
  }
113
  }
114
+
115
+
116
+
117
  $('#wplnst-filter-button').click(function() {
118
  var args = '', value;
119
  var fields = $(this).attr('data-fields').split(',');
120
  for (var i in fields) {
121
  value = $('#wplnst-filter-' + fields[i]).val();
122
+ if (typeof value != 'undefined' && '' !== value) {
123
  args += '&' + fields[i] + '=' + value;
124
+ }
125
  }
126
  window.location.href = $(this).attr('data-href') + args;
127
  return false;
assets/js/lightboxed/jquery.lightboxed.js CHANGED
@@ -1,7 +1,7 @@
1
  /*
2
  * $ lightboxed 1.0
3
  * By Pau Iglesias on seedplugins.com
4
- *
5
  * Based on lightbox_me 2.4 by Buck Wilson
6
  *
7
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,15 +28,16 @@
28
  $(document).on('keyup', observeKeyPress);
29
 
30
  function observeKeyPress(e) {
31
- if (fronts.length && (e.keyCode == 27 || (e.DOM_VK_ESCAPE == 27 && e.which==0)))
32
  fronts[fronts.length - 1].trigger('escPress');
 
33
  }
34
 
35
 
36
 
37
 
38
  $.fn.wplnst_lightboxed = function(options) {
39
-
40
  return this.each(function() {
41
 
42
 
@@ -47,21 +48,21 @@
47
 
48
 
49
  function init() {
50
-
51
  fronts.push($self);
52
  $('body').append($self.hide());
53
-
54
  zIndex = (false === zIndex)? settings.zIndex : zIndex + 1;
55
-
56
  if (settings.showOverlay) {
57
-
58
  $overlay = $('<div class="' + settings.classPrefix + '_overlay"/>');
59
-
60
  $('body').append($overlay);
61
-
62
  setOverlayHeight();
63
  $(window).resize(setOverlayHeight);
64
-
65
  $overlay.css({
66
  position : 'absolute',
67
  width : '100%',
@@ -72,9 +73,9 @@
72
  zIndex : zIndex,
73
  display : 'none',
74
  });
75
-
76
  $overlay.css(settings.overlayCSS);
77
-
78
  $overlay.fadeIn(settings.overlaySpeed, function() {
79
  setSelfPosition();
80
  $self[settings.appearEffect](settings.lightboxSpeed, function() {
@@ -88,24 +89,26 @@
88
  }
89
  });
90
  });
91
-
92
  } else {
93
-
94
  setSelfPosition();
95
  $self[settings.appearEffect](settings.lightboxSpeed, function() {
96
  $self.show();
97
  raiseOnLoad();
98
- if (settings.closeClickOutside)
99
  $(document).on('click', onClickOutside);
 
100
  });
101
  }
102
-
103
- if (settings.parentLightbox)
104
  settings.parentLightbox.fadeOut(200);
105
-
 
106
  $(window).resize(setSelfPosition).scroll(setSelfPosition);
107
  $(document).on('click', settings.closeSelector, onCloseSelector);
108
-
109
  $self.on('close', closeLightbox);
110
  $self.on('escPress', onEscPress);
111
  $self.on('reposition', setSelfPosition);
@@ -114,35 +117,37 @@
114
 
115
 
116
  function closeLightbox() {
117
-
118
  fronts.pop();
119
-
120
  if (settings.showOverlay) {
121
  $overlay.remove();
122
  $(window).unbind('resize', setOverlayHeight);
123
  } else if (settings.closeClickOutside) {
124
  $(document).off('click', onClickOutside);
125
  }
126
-
127
- if (settings.parentLightbox)
128
  settings.parentLightbox.fadeIn(200);
129
-
130
- if (settings.preventScroll)
 
131
  $('body').css('overflow', '');
132
-
 
133
  $(document).off('click', settings.closeSelector, onCloseSelector);
134
-
135
  $self.off('close', closeLightbox);
136
  $self.off('escPress', onEscPress);
137
  $self.off('reposition', setSelfPosition);
138
-
139
  $(window).unbind('resize', setSelfPosition);
140
  $(window).unbind('scroll', setSelfPosition);
141
-
142
  $self[settings.disappearEffect](settings.lightboxSpeed, function() {
143
  raiseOnClose();
144
  });
145
-
146
  //$self.hide();
147
  }
148
 
@@ -155,25 +160,25 @@
155
 
156
 
157
  function setSelfPosition() {
158
-
159
  $self.css({
160
  left : '50%',
161
- marginLeft : ($self.outerWidth() / 2) * -1,
162
  zIndex : zIndex + 1
163
  });
164
-
165
  if (($self.height() + 80 >= $(window).height()) && ($self.css('position') != 'absolute')) {
166
-
167
  var topOffset = $(document).scrollTop() + 40;
168
-
169
  $self.css({
170
  position : 'absolute',
171
  top : topOffset + 'px',
172
  marginTop : 0
173
  });
174
-
175
  } else if ($self.height() + 80 < $(window).height()) {
176
-
177
  settings.centered? $self.css({
178
  position : 'fixed',
179
  top : '50%',
@@ -181,17 +186,19 @@
181
  }) : $self.css({
182
  position : 'fixed'
183
  }).css(settings.modalCSS);
184
-
185
- if (settings.preventScroll)
186
  $('body').css('overflow', 'hidden');
 
187
  }
188
  }
189
 
190
 
191
 
192
  function onEscPress() {
193
- if (settings.closeEsc)
194
  closeLightbox();
 
195
  }
196
 
197
 
@@ -241,7 +248,7 @@
241
 
242
 
243
  $.fn.wplnst_lightboxed.defaults = {
244
-
245
  // Animation
246
  appearEffect : 'fadeIn',
247
  appearEase : '',
@@ -249,17 +256,17 @@
249
  disappearEase : '',
250
  lightboxSpeed : 200,
251
  overlaySpeed : 250,
252
-
253
  // Close
254
  closeSelector : '.wplnst_lightboxed_close',
255
  closeClickOutside : true,
256
  closeEsc : true,
257
-
258
  // Behavior
259
  showOverlay : true,
260
  parentLightbox : false,
261
  preventScroll : true,
262
-
263
  // Style
264
  centered : false,
265
  classPrefix : 'wplnst_lbx',
1
  /*
2
  * $ lightboxed 1.0
3
  * By Pau Iglesias on seedplugins.com
4
+ *
5
  * Based on lightbox_me 2.4 by Buck Wilson
6
  *
7
  * Licensed under the Apache License, Version 2.0 (the "License");
28
  $(document).on('keyup', observeKeyPress);
29
 
30
  function observeKeyPress(e) {
31
+ if (fronts.length && (e.keyCode == 27 || (e.DOM_VK_ESCAPE == 27 && e.which==0))) {
32
  fronts[fronts.length - 1].trigger('escPress');
33
+ }
34
  }
35
 
36
 
37
 
38
 
39
  $.fn.wplnst_lightboxed = function(options) {
40
+
41
  return this.each(function() {
42
 
43
 
48
 
49
 
50
  function init() {
51
+
52
  fronts.push($self);
53
  $('body').append($self.hide());
54
+
55
  zIndex = (false === zIndex)? settings.zIndex : zIndex + 1;
56
+
57
  if (settings.showOverlay) {
58
+
59
  $overlay = $('<div class="' + settings.classPrefix + '_overlay"/>');
60
+
61
  $('body').append($overlay);
62
+
63
  setOverlayHeight();
64
  $(window).resize(setOverlayHeight);
65
+
66
  $overlay.css({
67
  position : 'absolute',
68
  width : '100%',
73
  zIndex : zIndex,
74
  display : 'none',
75
  });
76
+
77
  $overlay.css(settings.overlayCSS);
78
+
79
  $overlay.fadeIn(settings.overlaySpeed, function() {
80
  setSelfPosition();
81
  $self[settings.appearEffect](settings.lightboxSpeed, function() {
89
  }
90
  });
91
  });
92
+
93
  } else {
94
+
95
  setSelfPosition();
96
  $self[settings.appearEffect](settings.lightboxSpeed, function() {
97
  $self.show();
98
  raiseOnLoad();
99
+ if (settings.closeClickOutside) {
100
  $(document).on('click', onClickOutside);
101
+ }
102
  });
103
  }
104
+
105
+ if (settings.parentLightbox) {
106
  settings.parentLightbox.fadeOut(200);
107
+ }
108
+
109
  $(window).resize(setSelfPosition).scroll(setSelfPosition);
110
  $(document).on('click', settings.closeSelector, onCloseSelector);
111
+
112
  $self.on('close', closeLightbox);
113
  $self.on('escPress', onEscPress);
114
  $self.on('reposition', setSelfPosition);
117
 
118
 
119
  function closeLightbox() {
120
+
121
  fronts.pop();
122
+
123
  if (settings.showOverlay) {
124
  $overlay.remove();
125
  $(window).unbind('resize', setOverlayHeight);
126
  } else if (settings.closeClickOutside) {
127
  $(document).off('click', onClickOutside);
128
  }
129
+
130
+ if (settings.parentLightbox) {
131
  settings.parentLightbox.fadeIn(200);
132
+ }
133
+
134
+ if (settings.preventScroll) {
135
  $('body').css('overflow', '');
136
+ }
137
+
138
  $(document).off('click', settings.closeSelector, onCloseSelector);
139
+
140
  $self.off('close', closeLightbox);
141
  $self.off('escPress', onEscPress);
142
  $self.off('reposition', setSelfPosition);
143
+
144
  $(window).unbind('resize', setSelfPosition);
145
  $(window).unbind('scroll', setSelfPosition);
146
+
147
  $self[settings.disappearEffect](settings.lightboxSpeed, function() {
148
  raiseOnClose();
149
  });
150
+
151
  //$self.hide();
152
  }
153
 
160
 
161
 
162
  function setSelfPosition() {
163
+
164
  $self.css({
165
  left : '50%',
166
+ marginLeft : ($self.outerWidth() / 2) * -1,
167
  zIndex : zIndex + 1
168
  });
169
+
170
  if (($self.height() + 80 >= $(window).height()) && ($self.css('position') != 'absolute')) {
171
+
172
  var topOffset = $(document).scrollTop() + 40;
173
+
174
  $self.css({
175
  position : 'absolute',
176
  top : topOffset + 'px',
177
  marginTop : 0
178
  });
179
+
180
  } else if ($self.height() + 80 < $(window).height()) {
181
+
182
  settings.centered? $self.css({
183
  position : 'fixed',
184
  top : '50%',
186
  }) : $self.css({
187
  position : 'fixed'
188
  }).css(settings.modalCSS);
189
+
190
+ if (settings.preventScroll) {
191
  $('body').css('overflow', 'hidden');
192
+ }
193
  }
194
  }
195
 
196
 
197
 
198
  function onEscPress() {
199
+ if (settings.closeEsc) {
200
  closeLightbox();
201
+ }
202
  }
203
 
204
 
248
 
249
 
250
  $.fn.wplnst_lightboxed.defaults = {
251
+
252
  // Animation
253
  appearEffect : 'fadeIn',
254
  appearEase : '',
256
  disappearEase : '',
257
  lightboxSpeed : 200,
258
  overlaySpeed : 250,
259
+
260
  // Close
261
  closeSelector : '.wplnst_lightboxed_close',
262
  closeClickOutside : true,
263
  closeEsc : true,
264
+
265
  // Behavior
266
  showOverlay : true,
267
  parentLightbox : false,
268
  preventScroll : true,
269
+
270
  // Style
271
  centered : false,
272
  classPrefix : 'wplnst_lbx',
constants.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+
5
+ /**
6
+ * Debug control constant (uncomment to activate)
7
+ */
8
+ /*if (!defined('WPLNST_DEBUG')) {
9
+ define('WPLNST_DEBUG', true);
10
+ }*/
11
+
12
+
13
+
14
+ /**
15
+ * Debug trace control constant (uncomment to activate)
16
+ */
17
+ /*if (!defined('WPLNST_DEBUG_OUTPUT')) {
18
+ define('WPLNST_DEBUG_OUTPUT', 'trace');
19
+ }*/
core/alive.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Alive class
5
- *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Alive {
10
 
@@ -28,78 +28,91 @@ class WPLNST_Core_Alive {
28
  * Check running crawler
29
  */
30
  public static function start($source) {
31
-
32
  // Load util file first
33
  require_once(WPLNST_PATH.'/core/util.php');
34
-
35
  // Version components
36
  $source::start_version();
37
-
38
  // Load common plugin dependencies
39
  wplnst_require('core', 'types');
40
-
41
  // Load custom nonce system
42
  wplnst_require('core', 'nonce/nonce');
43
-
44
  // Check crawl request arguments
45
  if (!(defined('DOING_AJAX') && DOING_AJAX) || empty($_GET['wplnst_crawler']) || empty($_GET['wplnst_nonce']) || empty($_GET['wplnst_slug'])) {
46
-
47
  // Check notifications
48
  if (!empty($_GET['wplnst_notify_email']) && 'on' == $_GET['wplnst_notify_email']) {
49
-
50
  // And finally check notify nonce
51
- if (!empty($_GET['wplnst_notify_nonce']) && self::verify_notify_nonce($_GET['wplnst_notify_nonce']))
52
  add_action('plugins_loaded', array($source, 'notify'));
53
-
 
54
  // Check cURL needed before
55
  } elseif (wplnst_is_curl_enabled()) {
56
-
57
  // Activity checks
58
  self::activity();
59
  }
60
-
61
  // Check this install crawler slug
62
  } elseif ($_GET['wplnst_slug'] == self::get_crawler_slug()) {
63
-
64
  /**
65
  * From here we are under crawler scope,
66
  * based on admin-ajax mode and special URL arguments.
67
  */
68
-
 
 
 
69
  // Check cURL loaded
70
  if (wplnst_is_curl_enabled()) {
71
-
 
 
 
72
  // Check scan integer and nonce argument
73
  $scan_id = (int) $_GET['wplnst_crawler'];
74
  if ($scan_id > 0) {
75
-
76
  // Check possible thread
77
  $thread_id = isset($_GET['wplnst_thread'])? $_GET['wplnst_thread'] : false;
78
-
 
 
 
79
  // Check scan and nonce
80
  if (false === ($scan_row = self::verify_crawler($scan_id, $thread_id, $_GET['wplnst_nonce']))) {
81
-
82
- // Debug
83
  wplnst_debug('scan '.$scan_id.' - thread '.(empty($thread_id)? 'false' : $thread_id).' - verify crawler error', 'alive');
84
-
85
  // Threads control
86
  } elseif (false === ($thread_id = self::threading($scan_row, $thread_id))) {
87
-
88
- // Debug
89
  wplnst_debug('scan '.$scan_id.' - thread '.$thread_id.' - threading error', 'alive');
90
-
91
  // Ok
92
  } else {
93
-
 
 
 
94
  // Run instance of crawler
95
  $source::instantiate_crawler($scan_row, $thread_id);
96
  }
97
  }
98
  }
99
-
100
- // Debug end
101
  wplnst_debug((empty($scan_row)? '' : 'scan '.$scan_row->scan_id.' - ').'thread '.(empty($thread_id)? '' : $thread_id).' terminate', 'alive');
102
-
103
  // End
104
  die;
105
  }
@@ -111,7 +124,7 @@ class WPLNST_Core_Alive {
111
  * Specific version components at start
112
  */
113
  protected static function start_version() {
114
-
115
  // Plugin definitions
116
  wplnst_require('core', 'plugin');
117
  }
@@ -122,16 +135,16 @@ class WPLNST_Core_Alive {
122
  * Start or continue active scan
123
  */
124
  public static function run($scan_id, $hash, $thread_id = false) {
125
-
126
  // Debug point
127
  wplnst_debug('scan '.$scan_id.' - '.(empty($thread_id)? '' : 'thread '.$thread_id.' ').'run', 'alive');
128
-
129
  // Check salt file
130
  WPLNST_Core_Nonce::check_salt_file();
131
-
132
  // Load cURL wrapper library
133
  wplnst_require('core', 'curl');
134
-
135
  // Spawn crawler call
136
  WPLNST_Core_CURL::spawn(array(
137
  'CURLOPT_URL' => self::get_crawler_url($scan_id, $hash, $thread_id),
@@ -147,91 +160,97 @@ class WPLNST_Core_Alive {
147
  * except at the end of a crawler process to check queued scans.
148
  */
149
  public static function activity($skip_check = false) {
150
-
151
  // Skip checks from the end
152
  if (!$skip_check) {
153
-
154
  // Avoid checks in plugins page
155
- if (is_admin() && false !== stripos($_SERVER['REQUEST_URI'], '/plugins.php'))
156
  return;
157
-
 
158
  // Preliminary check to avoid constant database queries
159
  $timestamp = (int) get_option('wplnst_crawler_timestamp');
160
- if ($timestamp > 0 && time() - $timestamp <= wplnst_get_nsetting('crawler_alive'))
161
  return;
162
-
 
163
  // Reset timer, and exit if this is the first time
164
  update_option('wplnst_crawler_timestamp', time());
165
- if (empty($timestamp))
166
  return;
 
167
  }
168
-
169
  // Retrieve active scans
170
  $max_scans = wplnst_get_nsetting('max_scans');
171
  $scans = self::get_ready_scans('play', 'started_at ASC', $max_scans);
172
-
173
  // Check queued merge
174
  if (count($scans) < $max_scans) {
175
  $scans_queued = self::get_ready_scans('queued', 'enqueued_at ASC', $max_scans - count($scans));
176
- if (!empty($scans_queued))
177
  $scans = array_merge($scans, $scans_queued);
 
178
  }
179
-
180
  // Globals
181
  global $wpdb;
182
-
183
  // Enum active scans
184
  foreach ($scans as $scan_info) {
185
-
186
  // Check threads cuota
187
  $threads = @json_decode($scan_info->threads, true);
188
  if (!empty($threads) && is_array($threads)) {
189
-
190
  // Initialize
191
  $active = 0;
192
-
193
  // Total timeout and minor correction
194
  $total_timeout = wplnst_get_nsetting('connect_timeout', $scan_info->connect_timeout) + wplnst_get_nsetting('request_timeout', $scan_info->request_timeout) + wplnst_get_nsetting('extra_timeout');
195
-
196
  // Count active threads
197
  foreach ($threads as $thread_id => $thread) {
198
  if ('on' == $thread['status']) {
199
- if ((time() - (int) $thread['timestamp']) <= $total_timeout)
200
  $active++;
 
201
  }
202
  }
203
-
204
  // Check free limits
205
- if ($active >= wplnst_get_nsetting('max_threads', $scan_info->max_threads))
206
  continue;
 
207
  }
208
-
209
  // Check and cast queued to play
210
  if ('queued' == $scan_info->status) {
211
-
212
  // Configure update
213
- $update = array('status' => 'play');
214
  $current_time = current_time('mysql', true);
215
-
216
  // First scan play
217
  if (empty($scan_info->started_at) || '0000-00-00 00:00:00' == $scan_info->started_at) {
218
  $update['started_at'] = $current_time;
219
  $update['stopped_at'] = '0000-00-00 00:00:00';
220
-
221
  // Continue
222
  } else {
223
-
224
  // Play again
225
  $update['continued_at'] = $current_time;
226
  }
227
-
228
  // And update
229
  $wpdb->update($wpdb->prefix.'wplnst_scans', $update, array('scan_id' => $scan_info->scan_id));
230
  }
231
-
232
- // Debug output
233
  wplnst_debug('scan '.$scan_info->scan_id.' launch from activity()', 'alive');
234
-
235
  // New thread
236
  self::run($scan_info->scan_id, $scan_info->hash);
237
  }
@@ -249,73 +268,94 @@ class WPLNST_Core_Alive {
249
  * This check runs under special URL dedicated to threading
250
  */
251
  private static function threading($scan_row, $current_thread_id) {
252
-
253
  // Globals
254
  global $wpdb;
255
-
256
  // Check threads array
257
  $threads = @json_decode($scan_row->threads, true);
258
  $threads = (empty($threads) || !is_array($threads))? array() : $threads;
259
-
 
 
 
260
  // Check invalid thread id
261
- if (!empty($current_thread_id) && !isset($threads[$current_thread_id]))
 
262
  return false;
263
-
 
264
  // Initialize
265
  $active = 0;
266
  $new_thread_id = false;
267
-
268
  // Total timeout and minor correction
269
  $total_timeout = wplnst_get_nsetting('connect_timeout', $scan_row->connect_timeout) + wplnst_get_nsetting('request_timeout', $scan_row->request_timeout) + wplnst_get_nsetting('extra_timeout');
270
-
 
 
 
271
  // Max crawler threads allowed
272
  $max_threads = wplnst_get_nsetting('max_threads', $scan_row->max_threads);
273
-
274
  // Inspect total active threads
275
  foreach ($threads as $thread_id => $thread) {
276
-
277
  // No checks for current thread
278
  if (!empty($current_thread_id) && $current_thread_id == $thread_id) {
279
  $active++;
280
-
281
  // Only active threads
282
  } elseif ('on' == $thread['status']) {
283
-
284
  // Timestamp limit
285
  if ((time() - (int) $thread['timestamp']) > $total_timeout) {
 
286
  $threads[$thread_id]['status'] = 'off';
287
-
288
  // Active
289
  } else {
290
  $active++;
291
  }
292
  }
293
  }
294
-
295
  // No current thread allowed
296
  if ($active > $max_threads) {
297
- if (!empty($current_thread_id))
 
298
  $threads[$current_thread_id]['status'] = 'off';
 
299
  $current_thread_id = false;
300
-
301
  // Check new thread
302
  } elseif ($active < $max_threads) {
303
  $active++;
304
  $new_thread_id = empty($threads)? 1 : (int) max(array_keys($threads)) + 1;
305
  $threads[$new_thread_id] = array('status' => 'on', 'timestamp' => time());
306
  }
307
-
308
  // Rebuild current thread
309
- if (!empty($current_thread_id))
310
  $threads[$current_thread_id] = array('status' => 'on', 'timestamp' => time());
311
-
 
 
 
 
 
 
 
 
 
312
  // Update threads data
313
- $wpdb->update($wpdb->prefix.'wplnst_scans', array('threads' => @json_encode($threads)), array('scan_id' => $scan_row->scan_id));
314
-
315
  // Launch new thread
316
- if (!empty($new_thread_id) && $active < $max_threads)
317
  self::run($scan_row->scan_id, $scan_row->hash);
318
-
 
319
  // Done
320
  return empty($current_thread_id)? $new_thread_id : $current_thread_id;
321
  }
@@ -331,42 +371,43 @@ class WPLNST_Core_Alive {
331
  * Retrieve active scan row identifier, ready state and threads value
332
  */
333
  private static function get_ready_scans($status, $order, $max_scans) {
334
-
335
  // Globals
336
  global $wpdb;
337
-
338
  // Retrieve scans
339
  $scans = $wpdb->get_results($wpdb->prepare('SELECT SQL_NO_CACHE scan_id, status, ready, hash, started_at, threads, max_threads, connect_timeout, request_timeout FROM '.$wpdb->prefix.'wplnst_scans WHERE ready = 1 AND status = %s ORDER BY '.esc_sql($order), $status));
340
-
341
  // Check results
342
- if (empty($scans) || !is_array($scans))
343
  return array();
344
-
 
345
  // Initialize
346
  $index = 0;
347
  $allowed = array();
348
-
349
  // Enum scans
350
  foreach ($scans as $scan) {
351
-
352
  // Check index
353
  $index++;
354
  if ($index > $max_scans) {
355
-
356
  // Queue scan
357
  if ('play' == $scan->status) {
358
  $current_time = current_time('mysql', true);
359
  $wpdb->query($wpdb->prepare('UPDATE '.$wpdb->prefix.'wplnst_scans SET status = "queued", enqueued_at = %s, stopped_at = %s WHERE scan_id = %d', $current_time, $current_time, $scan->scan_id));
360
  }
361
-
362
  // Next
363
  continue;
364
  }
365
-
366
  // Add allowed
367
  $allowed[] = $scan;
368
  }
369
-
370
  // Preserve allowed scans
371
  return $allowed;
372
  }
@@ -382,23 +423,26 @@ class WPLNST_Core_Alive {
382
  * Verify if crawler exists, is ready, and nonce
383
  */
384
  private static function verify_crawler($scan_id, $thread_id, $nonce) {
385
-
386
  // Globals
387
  global $wpdb;
388
-
389
  // Retrieve and check scan
390
  $scan_row = $wpdb->get_row($wpdb->prepare('SELECT SQL_NO_CACHE scan_id, status, ready, hash, threads, max_threads, connect_timeout, request_timeout FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
391
- if (empty($scan_row) || !is_object($scan_row))
392
  return false;
393
-
 
394
  // Check scan status
395
- if (empty($scan_row->status) || 'wait' == $scan_row->status || 'end' == $scan_row->status)
396
  return false;
397
-
 
398
  // Check scan ready
399
- if (empty($scan_row->ready) || 1 != (int) $scan_row->ready)
400
  return false;
401
-
 
402
  // Check nonce and return scan
403
  return self::verify_crawler_nonce($nonce, $scan_row->hash, $thread_id)? $scan_row : false;
404
  }
@@ -409,10 +453,10 @@ class WPLNST_Core_Alive {
409
  * Load a crawler instance
410
  */
411
  protected static function instantiate_crawler($scan_row, $thread_id) {
412
-
413
  // Load dependencies
414
  wplnst_require('core', 'crawler');
415
-
416
  // Instance
417
  WPLNST_Core_Crawler::instantiate(array(
418
  'scan_id' => $scan_row->scan_id,
@@ -445,18 +489,19 @@ class WPLNST_Core_Alive {
445
  * Compose current crawler URL
446
  */
447
  public static function get_crawler_url($scan_id, $hash, $thread_id = false) {
448
-
449
  // Default args
450
  $args = array(
451
  'wplnst_crawler' => $scan_id,
452
  'wplnst_nonce' => self::get_crawler_nonce($hash, $thread_id),
453
  'wplnst_slug' => self::get_crawler_slug(),
454
  );
455
-
456
  // Check thread arg
457
- if (!empty($thread_id))
458
  $args['wplnst_thread'] = $thread_id;
459
-
 
460
  // Compose URL
461
  return add_query_arg($args, rtrim(admin_url('admin-ajax.php'), '/'));
462
  }
@@ -467,20 +512,20 @@ class WPLNST_Core_Alive {
467
  * Retrieve, check or generate unique crawler slug
468
  */
469
  public static function get_crawler_slug() {
470
-
471
  // Retrieve current slug
472
  $crawler_slug = get_option('wplnst_crawler_slug');
473
-
474
  // Check valid page slug
475
  if (empty($crawler_slug) || 16 != strlen($crawler_slug) || !preg_match('/^[a-z0-9]+$/', $crawler_slug)) {
476
-
477
  // Generate new slug
478
  $crawler_slug = strtolower(WPLNST_Core_Nonce::generate_password(16, false, false));
479
-
480
  // And update
481
  update_option('wplnst_crawler_slug', $crawler_slug);
482
  }
483
-
484
  // Done
485
  return $crawler_slug;
486
  }
@@ -514,14 +559,14 @@ class WPLNST_Core_Alive {
514
  * Check pending notifications
515
  */
516
  public static function notify() {
517
-
518
  // Load translations
519
  WPLNST_Core_Plugin::load_plugin_textdomain();
520
-
521
  // Include and call class
522
  wplnst_require('core', 'notify');
523
  WPLNST_Core_Notify::check();
524
-
525
  // End
526
  die;
527
  }
1
  <?php
2
 
3
  /**
4
+ * Alive class
5
+ *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Alive {
10
 
28
  * Check running crawler
29
  */
30
  public static function start($source) {
31
+
32
  // Load util file first
33
  require_once(WPLNST_PATH.'/core/util.php');
34
+
35
  // Version components
36
  $source::start_version();
37
+
38
  // Load common plugin dependencies
39
  wplnst_require('core', 'types');
40
+
41
  // Load custom nonce system
42
  wplnst_require('core', 'nonce/nonce');
43
+
44
  // Check crawl request arguments
45
  if (!(defined('DOING_AJAX') && DOING_AJAX) || empty($_GET['wplnst_crawler']) || empty($_GET['wplnst_nonce']) || empty($_GET['wplnst_slug'])) {
46
+
47
  // Check notifications
48
  if (!empty($_GET['wplnst_notify_email']) && 'on' == $_GET['wplnst_notify_email']) {
49
+
50
  // And finally check notify nonce
51
+ if (!empty($_GET['wplnst_notify_nonce']) && self::verify_notify_nonce($_GET['wplnst_notify_nonce'])) {
52
  add_action('plugins_loaded', array($source, 'notify'));
53
+ }
54
+
55
  // Check cURL needed before
56
  } elseif (wplnst_is_curl_enabled()) {
57
+
58
  // Activity checks
59
  self::activity();
60
  }
61
+
62
  // Check this install crawler slug
63
  } elseif ($_GET['wplnst_slug'] == self::get_crawler_slug()) {
64
+
65
  /**
66
  * From here we are under crawler scope,
67
  * based on admin-ajax mode and special URL arguments.
68
  */
69
+
70
+ // Debug point
71
+ wplnst_debug('wplnst_slug arg ok', 'alive');
72
+
73
  // Check cURL loaded
74
  if (wplnst_is_curl_enabled()) {
75
+
76
+ // Debug point
77
+ wplnst_debug('curl enabled', 'alive');
78
+
79
  // Check scan integer and nonce argument
80
  $scan_id = (int) $_GET['wplnst_crawler'];
81
  if ($scan_id > 0) {
82
+
83
  // Check possible thread
84
  $thread_id = isset($_GET['wplnst_thread'])? $_GET['wplnst_thread'] : false;
85
+
86
+ // Debug point
87
+ wplnst_debug('Valid scan_id '.$scan_id, 'alive');
88
+
89
  // Check scan and nonce
90
  if (false === ($scan_row = self::verify_crawler($scan_id, $thread_id, $_GET['wplnst_nonce']))) {
91
+
92
+ // Debug point
93
  wplnst_debug('scan '.$scan_id.' - thread '.(empty($thread_id)? 'false' : $thread_id).' - verify crawler error', 'alive');
94
+
95
  // Threads control
96
  } elseif (false === ($thread_id = self::threading($scan_row, $thread_id))) {
97
+
98
+ // Debug point
99
  wplnst_debug('scan '.$scan_id.' - thread '.$thread_id.' - threading error', 'alive');
100
+
101
  // Ok
102
  } else {
103
+
104
+ // Debug point
105
+ wplnst_debug('scan '.$scan_id.' - thread '.$thread_id.' - instantiate crawler', 'alive');
106
+
107
  // Run instance of crawler
108
  $source::instantiate_crawler($scan_row, $thread_id);
109
  }
110
  }
111
  }
112
+
113
+ // Debug point
114
  wplnst_debug((empty($scan_row)? '' : 'scan '.$scan_row->scan_id.' - ').'thread '.(empty($thread_id)? '' : $thread_id).' terminate', 'alive');
115
+
116
  // End
117
  die;
118
  }
124
  * Specific version components at start
125
  */
126
  protected static function start_version() {
127
+
128
  // Plugin definitions
129
  wplnst_require('core', 'plugin');
130
  }
135
  * Start or continue active scan
136
  */
137
  public static function run($scan_id, $hash, $thread_id = false) {
138
+
139
  // Debug point
140
  wplnst_debug('scan '.$scan_id.' - '.(empty($thread_id)? '' : 'thread '.$thread_id.' ').'run', 'alive');
141
+
142
  // Check salt file
143
  WPLNST_Core_Nonce::check_salt_file();
144
+
145
  // Load cURL wrapper library
146
  wplnst_require('core', 'curl');
147
+
148
  // Spawn crawler call
149
  WPLNST_Core_CURL::spawn(array(
150
  'CURLOPT_URL' => self::get_crawler_url($scan_id, $hash, $thread_id),
160
  * except at the end of a crawler process to check queued scans.
161
  */
162
  public static function activity($skip_check = false) {
163
+
164
  // Skip checks from the end
165
  if (!$skip_check) {
166
+
167
  // Avoid checks in plugins page
168
+ if (is_admin() && false !== stripos($_SERVER['REQUEST_URI'], '/plugins.php')) {
169
  return;
170
+ }
171
+
172
  // Preliminary check to avoid constant database queries
173
  $timestamp = (int) get_option('wplnst_crawler_timestamp');
174
+ if ($timestamp > 0 && time() - $timestamp <= wplnst_get_nsetting('crawler_alive')) {
175
  return;
176
+ }
177
+
178
  // Reset timer, and exit if this is the first time
179
  update_option('wplnst_crawler_timestamp', time());
180
+ if (empty($timestamp)) {
181
  return;
182
+ }
183
  }
184
+
185
  // Retrieve active scans
186
  $max_scans = wplnst_get_nsetting('max_scans');
187
  $scans = self::get_ready_scans('play', 'started_at ASC', $max_scans);
188
+
189
  // Check queued merge
190
  if (count($scans) < $max_scans) {
191
  $scans_queued = self::get_ready_scans('queued', 'enqueued_at ASC', $max_scans - count($scans));
192
+ if (!empty($scans_queued)) {
193
  $scans = array_merge($scans, $scans_queued);
194
+ }
195
  }
196
+
197
  // Globals
198
  global $wpdb;
199
+
200
  // Enum active scans
201
  foreach ($scans as $scan_info) {
202
+
203
  // Check threads cuota
204
  $threads = @json_decode($scan_info->threads, true);
205
  if (!empty($threads) && is_array($threads)) {
206
+
207
  // Initialize
208
  $active = 0;
209
+
210
  // Total timeout and minor correction
211
  $total_timeout = wplnst_get_nsetting('connect_timeout', $scan_info->connect_timeout) + wplnst_get_nsetting('request_timeout', $scan_info->request_timeout) + wplnst_get_nsetting('extra_timeout');
212
+
213
  // Count active threads
214
  foreach ($threads as $thread_id => $thread) {
215
  if ('on' == $thread['status']) {
216
+ if ((time() - (int) $thread['timestamp']) <= $total_timeout) {
217
  $active++;
218
+ }
219
  }
220
  }
221
+
222
  // Check free limits
223
+ if ($active >= wplnst_get_nsetting('max_threads', $scan_info->max_threads)) {
224
  continue;
225
+ }
226
  }
227
+
228
  // Check and cast queued to play
229
  if ('queued' == $scan_info->status) {
230
+
231
  // Configure update
232
+ $update = array('status' => 'play');
233
  $current_time = current_time('mysql', true);
234
+
235
  // First scan play
236
  if (empty($scan_info->started_at) || '0000-00-00 00:00:00' == $scan_info->started_at) {
237
  $update['started_at'] = $current_time;
238
  $update['stopped_at'] = '0000-00-00 00:00:00';
239
+
240
  // Continue
241
  } else {
242
+
243
  // Play again
244
  $update['continued_at'] = $current_time;
245
  }
246
+
247
  // And update
248
  $wpdb->update($wpdb->prefix.'wplnst_scans', $update, array('scan_id' => $scan_info->scan_id));
249
  }
250
+
251
+ // Debug point
252
  wplnst_debug('scan '.$scan_info->scan_id.' launch from activity()', 'alive');
253
+
254
  // New thread
255
  self::run($scan_info->scan_id, $scan_info->hash);
256
  }
268
  * This check runs under special URL dedicated to threading
269
  */
270
  private static function threading($scan_row, $current_thread_id) {
271
+
272
  // Globals
273
  global $wpdb;
274
+
275
  // Check threads array
276
  $threads = @json_decode($scan_row->threads, true);
277
  $threads = (empty($threads) || !is_array($threads))? array() : $threads;
278
+
279
+ // Debug point
280
+ wplnst_debug('threading thread id '.$current_thread_id, 'alive');
281
+
282
  // Check invalid thread id
283
+ if (!empty($current_thread_id) && !isset($threads[$current_thread_id])) {
284
+ wplnst_debug('no registered thread', 'alive');
285
  return false;
286
+ }
287
+
288
  // Initialize
289
  $active = 0;
290
  $new_thread_id = false;
291
+
292
  // Total timeout and minor correction
293
  $total_timeout = wplnst_get_nsetting('connect_timeout', $scan_row->connect_timeout) + wplnst_get_nsetting('request_timeout', $scan_row->request_timeout) + wplnst_get_nsetting('extra_timeout');
294
+
295
+ // Sum the alive time plus 1 minute grace period
296
+ $total_timeout += 60 + (int) wplnst_get_nsetting('crawler_alive');
297
+
298
  // Max crawler threads allowed
299
  $max_threads = wplnst_get_nsetting('max_threads', $scan_row->max_threads);
300
+
301
  // Inspect total active threads
302
  foreach ($threads as $thread_id => $thread) {
303
+
304
  // No checks for current thread
305
  if (!empty($current_thread_id) && $current_thread_id == $thread_id) {
306
  $active++;
307
+
308
  // Only active threads
309
  } elseif ('on' == $thread['status']) {
310
+
311
  // Timestamp limit
312
  if ((time() - (int) $thread['timestamp']) > $total_timeout) {
313
+ wplnst_debug('inactivated an active thread - timestamp: '.$thread['timestamp'].' - total: '.$total_timeout.' - time: '.time());
314
  $threads[$thread_id]['status'] = 'off';
315
+
316
  // Active
317
  } else {
318
  $active++;
319
  }
320
  }
321
  }
322
+
323
  // No current thread allowed
324
  if ($active > $max_threads) {
325
+ wplnst_debug('max threads reached - active: '.$active.' - max threads: '.$max_threads);
326
+ if (!empty($current_thread_id)) {
327
  $threads[$current_thread_id]['status'] = 'off';
328
+ }
329
  $current_thread_id = false;
330
+
331
  // Check new thread
332
  } elseif ($active < $max_threads) {
333
  $active++;
334
  $new_thread_id = empty($threads)? 1 : (int) max(array_keys($threads)) + 1;
335
  $threads[$new_thread_id] = array('status' => 'on', 'timestamp' => time());
336
  }
337
+
338
  // Rebuild current thread
339
+ if (!empty($current_thread_id)) {
340
  $threads[$current_thread_id] = array('status' => 'on', 'timestamp' => time());
341
+ }
342
+
343
+ // Sanitize threads
344
+ $threads_safe = [];
345
+ foreach ($threads as $thread_id => $thread) {
346
+ if (!empty($thread) && is_array($thread) && !empty($thread['status']) && 'on' == $thread['status']) {
347
+ $threads_safe[$thread_id] = $thread;
348
+ }
349
+ }
350
+
351
  // Update threads data
352
+ $wpdb->update($wpdb->prefix.'wplnst_scans', array('threads' => @json_encode($threads_safe)), array('scan_id' => $scan_row->scan_id));
353
+
354
  // Launch new thread
355
+ if (!empty($new_thread_id) && $active < $max_threads) {
356
  self::run($scan_row->scan_id, $scan_row->hash);
357
+ }
358
+
359
  // Done
360
  return empty($current_thread_id)? $new_thread_id : $current_thread_id;
361
  }
371
  * Retrieve active scan row identifier, ready state and threads value
372
  */
373
  private static function get_ready_scans($status, $order, $max_scans) {
374
+
375
  // Globals
376
  global $wpdb;
377
+
378
  // Retrieve scans
379
  $scans = $wpdb->get_results($wpdb->prepare('SELECT SQL_NO_CACHE scan_id, status, ready, hash, started_at, threads, max_threads, connect_timeout, request_timeout FROM '.$wpdb->prefix.'wplnst_scans WHERE ready = 1 AND status = %s ORDER BY '.esc_sql($order), $status));
380
+
381
  // Check results
382
+ if (empty($scans) || !is_array($scans)) {
383
  return array();
384
+ }
385
+
386
  // Initialize
387
  $index = 0;
388
  $allowed = array();
389
+
390
  // Enum scans
391
  foreach ($scans as $scan) {
392
+
393
  // Check index
394
  $index++;
395
  if ($index > $max_scans) {
396
+
397
  // Queue scan
398
  if ('play' == $scan->status) {
399
  $current_time = current_time('mysql', true);
400
  $wpdb->query($wpdb->prepare('UPDATE '.$wpdb->prefix.'wplnst_scans SET status = "queued", enqueued_at = %s, stopped_at = %s WHERE scan_id = %d', $current_time, $current_time, $scan->scan_id));
401
  }
402
+
403
  // Next
404
  continue;
405
  }
406
+
407
  // Add allowed
408
  $allowed[] = $scan;
409
  }
410
+
411
  // Preserve allowed scans
412
  return $allowed;
413
  }
423
  * Verify if crawler exists, is ready, and nonce
424
  */
425
  private static function verify_crawler($scan_id, $thread_id, $nonce) {
426
+
427
  // Globals
428
  global $wpdb;
429
+
430
  // Retrieve and check scan
431
  $scan_row = $wpdb->get_row($wpdb->prepare('SELECT SQL_NO_CACHE scan_id, status, ready, hash, threads, max_threads, connect_timeout, request_timeout FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
432
+ if (empty($scan_row) || !is_object($scan_row)) {
433
  return false;
434
+ }
435
+
436
  // Check scan status
437
+ if (empty($scan_row->status) || 'wait' == $scan_row->status || 'end' == $scan_row->status) {
438
  return false;
439
+ }
440
+
441
  // Check scan ready
442
+ if (empty($scan_row->ready) || 1 != (int) $scan_row->ready) {
443
  return false;
444
+ }
445
+
446
  // Check nonce and return scan
447
  return self::verify_crawler_nonce($nonce, $scan_row->hash, $thread_id)? $scan_row : false;
448
  }
453
  * Load a crawler instance
454
  */
455
  protected static function instantiate_crawler($scan_row, $thread_id) {
456
+
457
  // Load dependencies
458
  wplnst_require('core', 'crawler');
459
+
460
  // Instance
461
  WPLNST_Core_Crawler::instantiate(array(
462
  'scan_id' => $scan_row->scan_id,
489
  * Compose current crawler URL
490
  */
491
  public static function get_crawler_url($scan_id, $hash, $thread_id = false) {
492
+
493
  // Default args
494
  $args = array(
495
  'wplnst_crawler' => $scan_id,
496
  'wplnst_nonce' => self::get_crawler_nonce($hash, $thread_id),
497
  'wplnst_slug' => self::get_crawler_slug(),
498
  );
499
+
500
  // Check thread arg
501
+ if (!empty($thread_id)) {
502
  $args['wplnst_thread'] = $thread_id;
503
+ }
504
+
505
  // Compose URL
506
  return add_query_arg($args, rtrim(admin_url('admin-ajax.php'), '/'));
507
  }
512
  * Retrieve, check or generate unique crawler slug
513
  */
514
  public static function get_crawler_slug() {
515
+
516
  // Retrieve current slug
517
  $crawler_slug = get_option('wplnst_crawler_slug');
518
+
519
  // Check valid page slug
520
  if (empty($crawler_slug) || 16 != strlen($crawler_slug) || !preg_match('/^[a-z0-9]+$/', $crawler_slug)) {
521
+
522
  // Generate new slug
523
  $crawler_slug = strtolower(WPLNST_Core_Nonce::generate_password(16, false, false));
524
+
525
  // And update
526
  update_option('wplnst_crawler_slug', $crawler_slug);
527
  }
528
+
529
  // Done
530
  return $crawler_slug;
531
  }
559
  * Check pending notifications
560
  */
561
  public static function notify() {
562
+
563
  // Load translations
564
  WPLNST_Core_Plugin::load_plugin_textdomain();
565
+
566
  // Include and call class
567
  wplnst_require('core', 'notify');
568
  WPLNST_Core_Notify::check();
569
+
570
  // End
571
  die;
572
  }
core/boot.php CHANGED
@@ -1,21 +1,21 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Boot check
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
 
10
  // Check class or constants conflict relative to other active plugins
11
  if (class_exists('WPLNST_Core_Alive') || defined('WPLNST_VERSION') || defined('WPLNST_FILE') || defined('WPLNST_PATH')) {
12
-
13
  // No execution allowed
14
  trigger_error(__('Detected another version of WP Link Status already active. Please deactivate it before and try again to activate this plugin.', 'wplnst'), E_USER_ERROR);
15
 
16
  // Check WP version via checking version expected function, because $wp_version may have been overwritten
17
  } elseif (function_exists('add_action') && !function_exists('is_main_query')) {
18
-
19
  // No compatible WP version
20
  trigger_error(__('Sorry, this version of WP Link Status requires WordPress 3.3 or later.', 'wplnst'), E_USER_ERROR);
21
  }
1
  <?php
2
 
3
  /**
4
+ * Boot check
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
 
10
  // Check class or constants conflict relative to other active plugins
11
  if (class_exists('WPLNST_Core_Alive') || defined('WPLNST_VERSION') || defined('WPLNST_FILE') || defined('WPLNST_PATH')) {
12
+
13
  // No execution allowed
14
  trigger_error(__('Detected another version of WP Link Status already active. Please deactivate it before and try again to activate this plugin.', 'wplnst'), E_USER_ERROR);
15
 
16
  // Check WP version via checking version expected function, because $wp_version may have been overwritten
17
  } elseif (function_exists('add_action') && !function_exists('is_main_query')) {
18
+
19
  // No compatible WP version
20
  trigger_error(__('Sorry, this version of WP Link Status requires WordPress 3.3 or later.', 'wplnst'), E_USER_ERROR);
21
  }
core/crawler.php CHANGED
@@ -4,10 +4,10 @@
4
  require_once(dirname(__FILE__).'/module.php');
5
 
6
  /**
7
- * WP Link Status Core Crawler class
8
  *
9
  * @package WP Link Status
10
- * @subpackage WP Link Status Core
11
  */
12
  class WPLNST_Core_Crawler extends WPLNST_Core_Module {
13
 
@@ -91,42 +91,48 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
91
  * Custom constructor
92
  */
93
  protected function on_construct($args = null) {
94
-
95
  // Check scan argument
96
  $scan_id = empty($args['scan_id'])? 0 : (int) $args['scan_id'];
97
- if (empty($scan_id))
98
  return;
99
-
 
100
  // Check thread argument
101
  $this->thread_id = empty($args['thread_id'])? 0 : (int) $args['thread_id'];
102
- if (empty($this->thread_id))
103
  return;
104
-
 
105
  // Crawler URL argument
106
  $this->crawler_url = empty($args['crawler_url'])? false : $args['crawler_url'];
107
- if (empty($this->crawler_url))
108
  return;
109
-
 
110
  // Check scan record
111
- if (false === ($this->scan = $this->get_scan_by_id($scan_id)))
112
  return;
 
113
 
114
  // Debug point
115
  $this->debug('__construct');
116
-
117
  // URL object
118
  $this->load_url_object();
119
-
120
  // All timeouts
121
  $this->set_timeouts();
122
-
123
  // Incoming POST request data
124
- if (!empty($_POST['url_id']))
125
  $this->request();
126
-
 
127
  // Check waiting links before next content data
128
- if (!$this->inspect())
129
  $this->content();
 
130
  }
131
 
132
 
@@ -144,7 +150,7 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
144
  // Local timeouts
145
  $this->connect_timeout = wplnst_get_nsetting('connect_timeout', $this->scan->threads->connect_timeout);
146
  $this->request_timeout = wplnst_get_nsetting('request_timeout', $this->scan->threads->request_timeout);
147
-
148
  // Timeouts sum and extra
149
  $this->total_timeout = $this->connect_timeout + $this->request_timeout + wplnst_get_nsetting('extra_timeout');
150
  }
@@ -155,82 +161,87 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
155
  * Result from a external request
156
  */
157
  private function request() {
158
-
159
  // Debug point
160
  $this->debug('request');
161
-
162
  // Check URL id
163
  $url_id = (int) $_POST['url_id'];
164
- if (empty($url_id))
165
  return;
166
-
 
167
  // Check URL record
168
- if (false === ($url = $this->scans->get_scan_url(array('id' => $url_id, 'no_cache' => true))))
169
  return;
170
-
 
171
  // Check URL status record
172
- if (false === ($rows = $this->scans->get_scan_url_status(array('url_id' => $url_id, 'scan_id' => $this->scan->id, 'no_cache' => true))))
173
  return;
174
-
 
175
  // Check URL status phase
176
- if (1 != count($rows) || in_array($rows[0]->phase, array('end', 'discard', 'failed')))
177
  return;
178
-
 
179
  // Check redirection mode
180
  $redirection = (!empty($_GET['wplnst_redirection']) && '1' == $_GET['wplnst_redirection']);
181
-
182
  // Analyze request
183
  wplnst_require('core', 'status');
184
  $status = new WPLNST_Core_Status($_POST);
185
 
186
  // Check discarded response
187
  $discard = empty($status->level)? false : (!in_array($status->level, $this->scan->status_levels) && !in_array($status->code, $this->scan->status_codes));
188
-
189
  // Check redirection steps
190
  $redirect_steps = @json_decode($rows[0]->redirect_steps, true);
191
- if (empty($redirect_steps) || !is_array($redirect_steps))
192
  $redirect_steps = array();
193
-
 
194
  // Normal mode
195
  if (!$this->scan->redir_status || !$redirection) {
196
-
197
  // Check redirection
198
  $phase_next = 'end';
199
  $redirect_url_id = 0;
200
  $redirect_url_status = "";
201
  $redirect_curl_errno = 0;
202
  if ($this->scan->redir_status && !$discard && 3 == $status->level && !empty($status->redirect_url)) {
203
-
204
  // Default redirection
205
  $redirect_url = $status->redirect_url;
206
-
207
  // Analyze
208
  $urlinfo = $this->urlo->parse($redirect_url, $url->url);
209
  if ($this->urlo->is_crawleable($urlinfo)) {
210
-
211
  // Copy final URL
212
  $redirect_url = $urlinfo['url'];
213
-
214
  // Search by main URL
215
  if (false !== ($redir_url = $this->scans->get_scan_url(array('url' => $redirect_url, 'no_cache' => true)))) {
216
-
217
  // Existing URL
218
  $phase_next = 'redir';
219
  $redirect_url_id = $redir_url->url_id;
220
-
221
  // New URL for this scan
222
  } elseif (false !== ($test_url_id = $this->scans->add_scan_url($urlinfo, $this->scan->id))) {
223
-
224
  // Mark to check
225
  $phase_next = 'redir';
226
  $redirect_url_id = $test_url_id;
227
  }
228
  }
229
-
230
  // Add possible fragment to save "As is"
231
  $redirect_url .= $urlinfo['fragment'];
232
  }
233
-
234
  // Update status data
235
  $this->scans->update_scan_url_status($url_id, $this->scan->id, array(
236
  'phase' => $discard? 'discard' : $phase_next,
@@ -248,7 +259,7 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
248
  'curl_errno' => $discard? 0 : $status->curl_errno,
249
  'requests' => $discard? 0 : (int) $rows[0]->requests + 1,
250
  ));
251
-
252
  // Update URL data
253
  $this->scans->update_scan_url($url_id, array(
254
  'last_scan_id' => $this->scan->id,
@@ -257,10 +268,10 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
257
  'last_curl_errno' => $status->curl_errno,
258
  'last_request_at' => $status->request_at,
259
  ));
260
-
261
  // Is Redirection
262
  } else {
263
-
264
  // Prepare update
265
  $update = array(
266
  'phase' => 'end',
@@ -268,33 +279,33 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
268
  'redirect_curl_errno' => $status->curl_errno,
269
  'requests' => (int) $rows[0]->requests + 1,
270
  );
271
-
272
  // Check new redirection
273
  if (empty($curl_errno) && 3 == $status->level && !empty($status->redirect_url) && ($rows[0]->requests + 1) <= wplnst_get_nsetting('max_redirs')) {
274
-
275
  // Check crawleable
276
  $urlinfo = $this->urlo->parse($status->redirect_url, $url->url);
277
  if ($this->urlo->is_crawleable($urlinfo)) {
278
-
279
  // Search by main URL
280
  if (false !== ($redir_url = $this->scans->get_scan_url(array('url' => $urlinfo['url'], 'no_cache' => true)))) {
281
-
282
  // Existing URL
283
  $redirect_url_id = $redir_url->url_id;
284
-
285
  // New URL for this scan
286
  } elseif (false !== ($test_url_id = $this->scans->add_scan_url($urlinfo, $this->scan->id))) {
287
-
288
  // Added URL
289
  $redirect_url_id = $test_url_id;
290
  }
291
-
292
  // For existing or correctly added URL
293
  if (!empty($redirect_url_id)) {
294
-
295
  // Copy old steps
296
  $redirect_steps[] = array('url' => $rows[0]->redirect_url, 'status' => $rows[0]->redirect_url_status);
297
-
298
  // New redir
299
  $update['phase'] = 'redir';
300
  $update['redirect_url'] = $urlinfo['url'].$urlinfo['fragment'];
@@ -304,14 +315,14 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
304
  }
305
  }
306
  }
307
-
308
  // Update status data
309
  $this->scans->update_scan_url_status($url_id, $this->scan->id, $update);
310
  }
311
-
312
  // Status codes
313
  $this->scans->set_scan_summary_status_codes($this->scan->id, $this->scan->status_levels, $this->scan->status_codes);
314
-
315
  // URLs summary
316
  $this->scans->set_scan_summary_urls_phases($this->scan->id);
317
  }
@@ -333,24 +344,25 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
333
 
334
  // Check if this scan is playing
335
  if ('play' != $this->scans->get_scan_status($this->scan->id)) {
336
-
337
  // Stopped or ended
338
  return true;
339
-
340
  // Retrieve next URL
341
  } elseif (false !== ($url = $this->inspect_wait())) {
342
-
343
  // Check no playing rows flag, and update started datetime
344
  if (true !== $url && false !== $this->scans->update_scan_url_status($url->url_id, $this->scan->id, array('phase' => 'play', 'started_at' => current_time('mysql', true)))) {
345
-
346
  // Debug point
347
  $this->debug('inspect request');
348
-
349
  // Check Crawler URL in redirection mode
350
  $crawler_url = $this->crawler_url;
351
- if (isset($url->redirection))
352
  $crawler_url = add_query_arg('wplnst_redirection', '1', $crawler_url);
353
-
 
354
  // Prepare POST fields
355
  $postfields = array(
356
  'url' => $url->url,
@@ -360,14 +372,13 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
360
  'request_timeout' => $this->request_timeout,
361
  'max_download' => wplnst_get_nsetting('max_download') * 1024,
362
  'back_url' => $crawler_url,
363
- 'debug' => wplnst_is_debug()? '1' : '0',
364
  'user_agent' => wplnst_get_tsetting('user_agent'),
365
  'nonce' => WPLNST_Core_Nonce::create_nonce($url->hash),
366
  );
367
-
368
  // Load cURL wrapper library
369
  wplnst_require('core', 'curl');
370
-
371
  // Spawn crawler call
372
  WPLNST_Core_CURL::spawn(array(
373
  'CURLOPT_URL' => plugins_url('core/requests/http.php', WPLNST_FILE),
@@ -376,11 +387,11 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
376
  'CURLOPT_POSTFIELDS' => http_build_query($postfields, null, '&'),
377
  'CURLOPT_HTTPHEADER' => array('Content-Type: application/x-www-form-urlencoded; charset=utf-8'),
378
  ));
379
-
380
  // Ends here, it's going out to check status
381
  return true;
382
  }
383
-
384
  // Check scan ending from all content
385
  } elseif ($this->content_end()) {
386
 
@@ -389,48 +400,52 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
389
 
390
  // Set "end" scan status
391
  $this->scans->end_scan($this->scan->id);
392
-
393
  // URLs status codes summary
394
  $this->scans->set_scan_summary_status_codes($this->scan->id, $this->scan->status_levels, $this->scan->status_codes, true);
395
-
396
  // URLs phases summary
397
  $this->scans->set_scan_summary_urls_phases($this->scan->id, true);
398
-
399
  // Update posts matched
400
- if ($this->scan->check_posts)
401
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'posts', true);
402
-
 
403
  // Update posts matched
404
- if ($this->scan->check_comments)
405
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'comments', true);
406
-
 
407
  // Update blogroll matched
408
- if ($this->scan->check_blogroll)
409
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'blogroll', true);
410
-
 
411
  // Remove discarded URLS
412
  $this->scans->remove_scan_discard_urls($this->scan->id);
413
-
414
  // Update real total posts
415
- if ($this->scan->check_posts)
416
  $this->scans->update_scan_trace($this->scan->id, array('total_posts' => $this->scans->get_scan_objects_count($this->scan->id, 'posts')));
417
-
 
418
  // Remove registered objects
419
  $this->scans->remove_scan_objects($this->scan->id);
420
-
421
  // Check notifications
422
  if ($this->scan->notify_default || ($this->scan->notify_address && !empty($this->scan->notify_address_email))) {
423
  wplnst_require('core', 'notify');
424
  WPLNST_Core_Notify::completed($this->scan);
425
  }
426
-
427
  // Check for queued scans
428
  $this->activity();
429
-
430
  // The end
431
  return true;
432
  }
433
-
434
  // No wait or play with timeout
435
  return false;
436
  }
@@ -441,46 +456,48 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
441
  * Inspect a waiting url to check
442
  */
443
  private function inspect_wait() {
444
-
445
  // Retrieve next wait
446
- if (false !== ($url = $this->scans->get_scan_url_waiting($this->scan->id)))
447
  return $url;
448
-
 
449
  // Check playing rows
450
- if (false === ($rows = $this->scans->get_scan_url_status(array('scan_id' => $this->scan->id, 'phase' => 'play', 'no_cache' => true, 'order' => 'started_at ASC'))))
451
  return false;
452
-
 
453
  // Max requests allowed
454
  $max_requests = wplnst_get_nsetting('max_requests');
455
-
456
  // Enum playing rows
457
  foreach ($rows as $row) {
458
-
459
  // Check timeouted
460
  if (time() - strtotime($row->started_at.' UTC') > $this->total_timeout) {
461
-
462
  // Check max requests
463
  if ($row->requests >= $max_requests) {
464
-
465
  // Mark as a request phase
466
  $this->scans->update_scan_url_status($url->url_id, $this->scan->id, array('phase' => 'failed'));
467
-
468
  // Retrieve URL
469
  } elseif (false !== ($url = $this->scans->get_scan_url(array('id' => $row->url_id, 'no_cache' => true)))) {
470
-
471
  // Update from play to wait
472
  if (false !== $this->scans->update_scan_url_status($url->url_id, $this->scan->id, array('phase' => 'wait'))) {
473
-
474
  // URLs summary
475
  $this->scans->set_scan_summary_urls_phases($this->scan->id);
476
-
477
  // Done
478
  return $url;
479
  }
480
  }
481
  }
482
  }
483
-
484
  // Playing rows
485
  return false;
486
  }
@@ -496,24 +513,25 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
496
  * Initialize post args
497
  */
498
  private function set_post_args() {
499
-
500
  // Check previous
501
- if (isset($this->post_args))
502
  return;
503
-
 
504
  // Initialize arguments
505
  $this->post_args = array();
506
-
507
  // Prepare types and status fragments
508
  $this->post_args['post_types'] = (1 == count($this->scan->post_types))? '= "'.esc_sql($this->scan->post_types[0]).'"' : 'IN ("'.implode('", "', array_map('esc_sql', $this->scan->post_types)).'")';
509
  $this->post_args['post_status'] = (1 == count($this->scan->post_status))? '= "'.esc_sql($this->scan->post_status[0]).'"' : 'IN ("'.implode('", "', array_map('esc_sql', $this->scan->post_status)).'")';
510
-
511
  // Time scope argument
512
  $this->post_args['time_scope'] = $this->get_time_scope_arg('post_date_gmt');
513
-
514
  // Check order
515
  $this->post_args['order_by'] = 'post_date_gmt '.(('asc' == $this->scan->crawl_order)? 'ASC' : 'DESC');
516
-
517
  // Filters arguments
518
  $this->post_args['content_filters'] = $this->get_content_filters_arg('post_content');
519
  }
@@ -524,24 +542,25 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
524
  * Initialize comments args
525
  */
526
  private function set_comment_args() {
527
-
528
  // Check previous
529
- if (isset($this->comment_args))
530
  return;
531
-
 
532
  // Initialize
533
  $this->comment_args = array();
534
-
535
  // Comment status
536
  $comment_types = WPLNST_Core_Types::get_comment_types_values($this->scan->comment_types);
537
  $this->comment_args['comment_status'] = ' AND comment_approved '.((1 == count($comment_types))? '= "'.esc_sql($comment_types[0]).'"' : 'IN ("'.implode('", "', array_map('esc_sql', $comment_types)).'")');
538
-
539
  // Time scope argument
540
  $this->comment_args['time_scope'] = $this->get_time_scope_arg('comment_date_gmt');
541
 
542
  // Filters arguments
543
  $this->comment_args['content_filters'] = $this->get_content_filters_arg('comment_content');
544
-
545
  // Check order
546
  $this->comment_args['order_by'] = 'comment_date_gmt '.(('asc' == $this->scan->crawl_order)? 'ASC' : 'DESC');
547
  }
@@ -552,14 +571,15 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
552
  * Initialize blogroll args
553
  */
554
  private function set_blogroll_args() {
555
-
556
  // Check previous
557
- if (isset($this->blogroll_args))
558
  return;
559
-
 
560
  // Initialize arguments
561
  $this->blogroll_args = array();
562
-
563
  // Check order
564
  $this->blogroll_args['order_by'] = 'link_id '.(('asc' == $this->scan->crawl_order)? 'ASC' : 'DESC');
565
  }
@@ -570,80 +590,86 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
570
  * Process next post
571
  */
572
  private function content() {
573
-
574
  // Debug point
575
  $this->debug('content');
576
-
577
  // No script timeout
578
  set_time_limit(0);
579
-
580
  // Retrieve trace array
581
  $trace = $this->scans->get_scan_trace($this->scan->id);
582
-
583
  // Initialize process flags
584
  $process_posts = $process_comments = $process_blogroll = false;
585
-
586
-
587
  /* Check content */
588
-
589
  // Check posts
590
  if ($this->scan->check_posts && empty($trace['populated_posts'])) {
591
  $process_posts = true;
592
  $this->content_total('posts');
593
  }
594
-
595
  // Check comments
596
  if ($this->scan->check_comments && empty($trace['populated_comments'])) {
597
  $process_comments = true;
598
- if (empty($trace['total_comments_check']) || !$process_posts)
599
  $this->content_total('comments');
 
600
  }
601
-
602
  // Check blogroll
603
  if ($this->scan->check_blogroll && empty($trace['populated_blogroll'])) {
604
-
605
  // Check links arg, if not update trace
606
  if (!in_array('links', $this->scan->link_types)) {
607
  $this->total_blogroll = 0;
608
  $this->scans->update_scan_trace($this->scan->id, array('populated_blogroll' => true, 'total_blogroll' => 0));
609
-
610
  // Continue
611
  } else {
612
-
613
  // Mark for process
614
  $process_blogroll = true;
615
-
616
  // Check first update
617
- if (empty($trace['total_blogroll_check']) || (!$process_posts && !$process_comments))
618
  $this->content_total('blogroll');
 
619
  }
620
  }
621
-
622
-
623
  // Common filters
624
  add_filter('wplnst_relative_parent_url', array(&$this, 'parent_permalink'));
625
-
626
-
627
  /* Processing objects */
628
-
629
  // Process posts
630
- if ($process_posts && !$this->content_posts())
631
  return;
632
-
 
633
  // Process comments
634
- if ($process_comments && !$this->content_comments())
635
  return;
636
-
 
637
  // Process blogroll
638
- if ($process_blogroll && !$this->content_blogroll())
639
  return;
640
-
641
-
 
642
  /* External work or run again */
643
-
644
  // More data or restart
645
- if (!$this->inspect())
646
  $this->restart();
 
647
  }
648
 
649
 
@@ -652,22 +678,25 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
652
  * Check if this is the end of all content types
653
  */
654
  private function content_end() {
655
-
656
  // Initialize
657
  $the_end = true;
658
-
659
  // Check posts
660
- if ($this->scan->check_posts)
661
  $the_end = (false !== $this->scans->get_scan_trace($this->scan->id, 'populated_posts'));
662
-
 
663
  // Check comments
664
- if ($the_end && $this->scan->check_comments)
665
  $the_end = (false !== $this->scans->get_scan_trace($this->scan->id, 'populated_comments'));
 
666
 
667
  // Check blogroll
668
- if ($the_end && $this->scan->check_blogroll)
669
  $the_end = (false !== $this->scans->get_scan_trace($this->scan->id, 'populated_blogroll'));
670
-
 
671
  // Done
672
  return $the_end;
673
  }
@@ -678,31 +707,33 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
678
  * Time scope limits
679
  */
680
  private function get_time_scope_arg($field) {
681
-
682
  // First basic check
683
- if (empty($this->scan->time_scope) || 'anytime' == $this->scan->time_scope)
684
  return '';
685
-
 
686
  // Check real value
687
- if (!in_array($this->scan->time_scope, array_keys(WPLNST_Core_Types::get_time_scopes())))
688
  return '';
689
-
 
690
  // Yesterday
691
  if ('yesterday' == $this->scan->time_scope) {
692
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-1 days")).'"';
693
-
694
  // From one week ago
695
  } elseif ('7days' == $this->scan->time_scope) {
696
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-7 days")).'"';
697
-
698
  // From 15 days ago
699
  } elseif ('15days' == $this->scan->time_scope) {
700
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-15 days")).'"';
701
-
702
  // From 1 month ago
703
  } elseif ('month' == $this->scan->time_scope) {
704
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-1 months")).'"';
705
-
706
  // From 3 months ago
707
  } elseif ('3months' == $this->scan->time_scope) {
708
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-3 months")).'"';
@@ -712,11 +743,11 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
712
 
713
  } elseif ('year' == $this->scan->time_scope) {
714
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-1 years")).'"';
715
-
716
  } elseif ('custom' == $this->scan->time_scope) {
717
  // Pending
718
  }
719
-
720
  // Check value and compose subquery
721
  return isset($back_date)? ' AND '.$field.$back_date : '';
722
  }
@@ -727,17 +758,19 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
727
  * Content filters in query
728
  */
729
  private function get_content_filters_arg($field, $op = ' AND ') {
730
-
731
  // Content matches
732
  $matches = $this->filter_for_queries();
733
- if (empty($matches))
734
  return '';
735
-
 
736
  // Prepare likes
737
  $likes = array();
738
- foreach ($matches as $match)
739
  $likes[] = $field.' LIKE "%'.addcslashes($match, '_%\\').'%"';
740
-
 
741
  // Likes fragment
742
  return $op.((1 == count($likes))? $likes[0] : '('.implode(' OR ', $likes).')');
743
  }
@@ -748,151 +781,151 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
748
  * Update total posts
749
  */
750
  private function content_total($type, $final = false) {
751
-
752
  // Globals
753
  global $wpdb;
754
-
755
  // Retrieve trace array
756
  $trace = $this->scans->get_scan_trace($this->scan->id);
757
-
758
  // Update posts
759
  if ('posts' == $type) {
760
-
761
  // Debug point
762
  $this->debug('content_total posts');
763
-
764
  // Check trace value
765
  $total_posts = empty($trace['total_posts'])? 0 : (int) $trace['total_posts'];
766
-
767
  // Total posts check
768
  $timestamp = empty($trace['total_posts_check'])? false : (int) $trace['total_posts_check'];
769
  if (false === $timestamp || (time() - $timestamp) >= wplnst_get_nsetting('total_objects')) {
770
-
771
  // Debug point
772
  $this->debug('content_total posts update');
773
-
774
  // Mark checked time
775
  $this->scans->update_scan_trace($this->scan->id, array('total_posts_check' => time()));
776
-
777
  // Set filters
778
  $this->set_post_args();
779
-
780
  // Prepare query
781
  $sql = 'SELECT COUNT(*) FROM '.$wpdb->posts.' WHERE post_type '.$this->post_args['post_types'].' AND post_status '.$this->post_args['post_status'].$this->post_args['time_scope'].$this->post_args['content_filters'];
782
-
783
  // Check last date condition
784
  $last_date_gmt = $this->scans->get_scan_trace($this->scan->id, 'last_post_date_gmt');
785
  if (empty($last_date_gmt)) {
786
-
787
  // Total posts without restrictions
788
  $total_posts = (int) $wpdb->get_var($sql);
789
-
790
  // Check
791
  } else {
792
-
793
  // Sum processed and no-processed
794
  $where = ' AND post_date_gmt '.(('asc' == $this->scan->crawl_order)? '>=' : '<=').' "'.esc_sql($last_date_gmt).'"';
795
  $total_posts = (int) $this->scans->get_scan_trace($this->scan->id, 'posts_index') + (int) $wpdb->get_var($sql.$where.' AND ID NOT IN (SELECT object_id FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = '.esc_sql($this->scan->id).' AND object_type = "posts")');
796
  }
797
-
798
  // Update total posts
799
  $this->scans->update_scan_trace($this->scan->id, array('total_posts' => $total_posts));
800
  }
801
-
802
  // Assign results
803
  $this->total_posts = $total_posts;
804
-
805
  // Update total comments
806
  } elseif ('comments' == $type) {
807
-
808
  // Debug point
809
  $this->debug('content_total comments');
810
-
811
  // Check trace value
812
  $total_comments = empty($trace['total_comments'])? 0 : (int) $trace['total_comments'];
813
-
814
  // Total comments check
815
  $timestamp = empty($trace['total_comments_check'])? false : (int) $trace['total_comments_check'];
816
  if (false === $timestamp || (time() - $timestamp) >= wplnst_get_nsetting('total_objects')) {
817
-
818
  // Debug point
819
  $this->debug('content_total comments update');
820
-
821
  // Mark checked time
822
  $this->scans->update_scan_trace($this->scan->id, array('total_comments_check' => time()));
823
-
824
  // Set filters
825
  $this->set_comment_args();
826
-
827
  // Prepare query
828
  $sql = 'SELECT COUNT(*) FROM '.$wpdb->comments.' WHERE 1 = 1 '.$this->comment_args['comment_status'].$this->comment_args['time_scope'].$this->comment_args['content_filters'];
829
-
830
  // Check last date condition
831
  $last_date_gmt = $this->scans->get_scan_trace($this->scan->id, 'last_comment_date_gmt');
832
  if (empty($last_date_gmt)) {
833
-
834
  // Total comments without restrictions
835
  $total_comments = (int) $wpdb->get_var($sql);
836
-
837
  // Check
838
  } else {
839
-
840
  // Sum processed and no-processed
841
  $where = ' AND comment_date_gmt '.(('asc' == $this->scan->crawl_order)? '>=' : '<=').' "'.esc_sql($last_date_gmt).'"';
842
  $total_comments = (int) $this->scans->get_scan_trace($this->scan->id, 'comments_index') + (int) $wpdb->get_var($sql.$where.' AND comment_ID NOT IN (SELECT object_id FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = '.esc_sql($this->scan->id).' AND object_type = "comments")');
843
  }
844
-
845
  // Update total comments
846
  $this->scans->update_scan_trace($this->scan->id, array('total_comments' => $total_comments));
847
  }
848
-
849
  // Assign results
850
  $this->total_comments = $total_comments;
851
-
852
  // Update total blogroll links
853
  } elseif ('blogroll' == $type) {
854
-
855
  // Debug point
856
  $this->debug('content_total blogroll');
857
-
858
  // Check trace value
859
  $total_blogroll = empty($trace['total_blogroll'])? 0 : (int) $trace['total_blogroll'];
860
-
861
  // Total blogroll check
862
  $timestamp = empty($trace['total_blogroll_check'])? false : (int) $trace['total_blogroll_check'];
863
  if (false === $timestamp || (time() - $timestamp) >= wplnst_get_nsetting('total_objects')) {
864
-
865
  // Debug point
866
  $this->debug('content_total blogroll update');
867
-
868
  // Mark checked time
869
  $this->scans->update_scan_trace($this->scan->id, array('total_blogroll_check' => time()));
870
-
871
  // Set filters
872
  $this->set_blogroll_args();
873
-
874
  // Prepare query
875
  $sql = 'SELECT COUNT(*) FROM '.$wpdb->links;
876
-
877
  // Check last identifier condition
878
  $last_id = (int) $this->scans->get_scan_trace($this->scan->id, 'last_blogroll_id');
879
  if (empty($last_id)) {
880
-
881
  // Total blogroll without restrictions
882
  $total_blogroll = (int) $wpdb->get_var($sql);
883
-
884
  // Check
885
  } else {
886
-
887
  // Sum processed and no-processed
888
  $where = ' WHERE link_id '.(('asc' == $this->scan->crawl_order)? '>' : '<').' '.$last_id;
889
  $total_blogroll = (int) $this->scans->get_scan_trace($this->scan->id, 'blogroll_index') + (int) $wpdb->get_var($sql.$where.' AND link_id NOT IN (SELECT object_id FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = '.esc_sql($this->scan->id).' AND object_type = "blogroll")');
890
  }
891
-
892
  // Update total blogroll
893
  $this->scans->update_scan_trace($this->scan->id, array('total_blogroll' => $total_blogroll));
894
  }
895
-
896
  // Assign results
897
  $this->total_blogroll = $total_blogroll;
898
  }
@@ -904,7 +937,7 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
904
  * Obtains and process contents from posts
905
  */
906
  private function content_posts() {
907
-
908
  // Recursion limit
909
  static $recursion;
910
  $recursion = isset($recursion)? 1 : $recursion + 1;
@@ -912,91 +945,96 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
912
  $this->restart();
913
  return false;
914
  }
915
-
916
  // Content max pack
917
  $this->pack_index++;
918
  if ($this->pack_index > wplnst_get_nsetting('max_pack')) {
919
  $this->restart();
920
  return false;
921
  }
922
-
923
  // Check next post
924
  if (false !== ($post = $this->content_posts_next())) {
925
-
926
  // Register object
927
- if (!$this->scans->register_scan_object($this->scan->id, $post->ID, 'posts', $post->post_date_gmt))
928
  return $this->content_posts();
929
-
 
930
  // Update last date gmt
931
  $this->scans->update_scan_trace($this->scan->id, array('last_post_date_gmt' => $post->post_date_gmt));
932
-
933
  // Update posts index
934
  $this->scans->update_scan_trace($this->scan->id, array('posts_index' => $this->scans->get_scan_objects_count($this->scan->id, 'posts')));
935
-
936
  // Initialize
937
  $links_added = array();
938
  $images_added = array();
939
  $custom_fields_links_added = array();
940
  $custom_fields_images_added = array();
941
-
942
  // Parent permalink reference
943
  $parent_url = array('post_id' => $post->ID);
944
-
945
  // Process content
946
  if (!empty($post->post_content)) {
947
-
948
  // Process links
949
  if (in_array('links', $this->scan->link_types)) {
950
  $links = $this->extract_links($post->post_content, $parent_url, $post->ID, 'posts', $post->post_type, 'post_content', $post->post_date_gmt);
951
- if (!empty($links))
952
  $links_added = $this->save($links, $post->ID);
 
953
  }
954
-
955
  // Process images
956
  if (in_array('images', $this->scan->link_types)) {
957
  $images = $this->extract_images($post->post_content, $parent_url, $post->ID, 'posts', $post->post_type, 'post_content', $post->post_date_gmt);
958
- if (!empty($images))
959
  $images_added = $this->save($images, $post->ID);
 
960
  }
961
  }
962
-
963
  // Check custom fields
964
  if (!empty($this->scan->custom_fields)) {
965
-
966
  // Retrieve post custom fields
967
  $post_metas = $this->scans->get_post_metas($post->ID);
968
  if (!empty($post_metas) && is_array($post_metas)) {
969
-
970
  // First compare field by key
971
  foreach ($this->scan->custom_fields as $field) {
972
-
973
  // Check field
974
- if (empty($field['type']) || !isset($field['name']))
975
  continue;
976
-
 
977
  // Check existing name
978
  $name = $field['name'];
979
  if (isset($post_metas[$name])) {
980
-
981
  // Check custom field content
982
  $post_meta = $post_metas[$name];
983
  if (!empty($post_meta) && is_array($post_meta)) {
984
-
985
  // Enum values
986
  foreach ($post_meta as $meta_id => $value) {
987
-
988
  // Sanitize
989
  $value = trim($value);
990
- if (empty($value))
991
  continue;
992
-
 
993
  // Direct URL
994
  if ('url' == $field['type']) {
995
-
996
  // Check URL
997
  $urlinfo = $this->urlo->parse($value, $parent_url);
998
  if ($this->filter_include_urls($urlinfo['url']) && $this->filter_exclude_urls($urlinfo['url'])) {
999
-
1000
  // Create link array
1001
  $link = array_merge($urlinfo, array(
1002
  'anchor' => '',
@@ -1007,26 +1045,28 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1007
  'object_field' => 'custom_field_url_'.$meta_id.'_'.$name,
1008
  'object_date_gmt' => $post->post_date_gmt,
1009
  ));
1010
-
1011
  // Author links
1012
  $custom_fields_links_added = $this->save(array($link), $post->ID);
1013
  }
1014
-
1015
  // HTML
1016
  } else {
1017
-
1018
  // Process links
1019
  if (in_array('links', $this->scan->link_types)) {
1020
  $links = $this->extract_links($value, $parent_url, $post->ID, 'posts', $post->post_type, 'custom_field_html_'.$meta_id.'_'.$name, $post->post_date_gmt);
1021
- if (!empty($links))
1022
  $custom_fields_links_added = $this->save($links, $post->ID);
 
1023
  }
1024
-
1025
  // Process images
1026
  if (in_array('images', $this->scan->link_types)) {
1027
  $images = $this->extract_images($value, $parent_url, $post->ID, 'posts', $post->post_type, 'custom_field_html_'.$meta_id.'_'.$name, $post->post_date_gmt);
1028
- if (!empty($images))
1029
  $custom_fields_images_added = $this->save($images, $post->ID);
 
1030
  }
1031
  }
1032
  }
@@ -1035,43 +1075,46 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1035
  }
1036
  }
1037
  }
1038
-
1039
  // Update stats for summary
1040
  if (!(empty($links_added) && empty($images_added) && empty($custom_fields_links_added) && empty($custom_fields_images_added))) {
1041
-
1042
  // Update URLs phases
1043
  $this->scans->set_scan_summary_urls_phases($this->scan->id);
1044
-
1045
  // Update objects matched
1046
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'posts');
1047
-
1048
  // Totals of content for each URL status added
1049
  $added = array_unique(array_merge($links_added, $images_added, $custom_fields_links_added, $custom_fields_images_added));
1050
- foreach ($added as $url_id)
1051
  $this->scans->set_scan_url_status_total_content($url_id, $this->scan->id);
1052
-
 
1053
  // Check inspect data
1054
- if ($this->inspect())
1055
  return false;
 
1056
  }
1057
-
1058
  // Empty
1059
  } elseif ($this->scans->get_scan_objects_count($this->scan->id, 'posts') >= $this->total_posts) {
1060
-
1061
  // Update populated status
1062
  $this->scans->update_scan_trace($this->scan->id, array('populated_posts' => true));
1063
-
1064
  // Check inspect data
1065
- if ($this->inspect())
1066
  return false;
1067
-
 
1068
  // Check data to inspect
1069
  } elseif ($this->inspect()) {
1070
-
1071
  // Working
1072
  return false;
1073
  }
1074
-
1075
  // End or next post
1076
  return $this->scans->get_scan_trace($this->scan->id, 'populated_posts')? true : $this->content_posts();
1077
  }
@@ -1082,50 +1125,53 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1082
  * Retrieve next post
1083
  */
1084
  private function content_posts_next($exceptions = array()) {
1085
-
1086
  // Globals
1087
  global $wpdb;
1088
-
1089
  // Initialize
1090
  $where = '1 = 1';
1091
-
1092
- // Check exceptions
1093
- if (!empty($exceptions))
1094
- $where .= ' AND ID NOT IN ('.implode(',', array_map('intval', $exceptions)).')';
1095
-
 
1096
  // Check last date condition
1097
  $last_date_gmt = $this->scans->get_scan_trace($this->scan->id, 'last_post_date_gmt');
1098
- if (!empty($last_date_gmt))
1099
  $where .= ' AND post_date_gmt '.(('asc' == $this->scan->crawl_order)? '>=' : '<=').' "'.esc_sql($last_date_gmt).'"';
1100
-
 
1101
  // Set arguments
1102
  $this->set_post_args();
1103
-
1104
  // Retrieve next post
1105
  $post = $wpdb->get_row('SELECT ID, post_content, post_date_gmt, post_type FROM '.$wpdb->posts.' WHERE '.$where.' AND post_type '.$this->post_args['post_types'].' AND post_status '.$this->post_args['post_status'].$this->post_args['time_scope'].$this->post_args['content_filters'].' ORDER BY '.$this->post_args['order_by'].' LIMIT 1');
1106
-
1107
  // Check if post is previously registered
1108
  if (!empty($post) && $this->scans->scan_object_exists($this->scan->id, $post->ID, 'posts')) {
1109
-
1110
  // Prepare identifiers
1111
  $ids = array($post->ID);
1112
-
1113
  // Check same value of last date
1114
  if ($post->post_date_gmt == $last_date_gmt) {
1115
-
1116
  // Check more identifiers with same date
1117
  $existing_ids = $this->scans->get_scan_objects_ids_by_date($this->scan->id, 'posts', $last_date_gmt);
1118
- if (!empty($existing_ids) && is_array($existing_ids))
1119
  $ids = array_unique(array_merge($ids, $existing_ids));
 
1120
  }
1121
-
1122
  // Add exceptions
1123
  $exceptions = empty($exceptions)? $ids : array_unique(array_merge($exceptions, $ids));
1124
-
1125
  // Next post with exceptions
1126
  $post = $this->content_posts_next($exceptions);
1127
  }
1128
-
1129
  // Done
1130
  return empty($post)? false : $post;
1131
  }
@@ -1136,7 +1182,7 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1136
  * Obtains and process contents from comments
1137
  */
1138
  private function content_comments() {
1139
-
1140
  // Recursion limit
1141
  static $recursion;
1142
  $recursion = isset($recursion)? 1 : $recursion + 1;
@@ -1144,63 +1190,66 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1144
  $this->restart();
1145
  return false;
1146
  }
1147
-
1148
  // Content max pack
1149
  $this->pack_index++;
1150
  if ($this->pack_index > wplnst_get_nsetting('max_pack')) {
1151
  $this->restart();
1152
  return false;
1153
  }
1154
-
1155
  // Check next comment
1156
  if (false !== ($comment = $this->content_comments_next())) {
1157
-
1158
  // Register object
1159
- if (!$this->scans->register_scan_object($this->scan->id, $comment->comment_ID, 'comments', $comment->comment_date_gmt))
1160
  return $this->content_comments();
1161
-
 
1162
  // Update last date gmt
1163
  $this->scans->update_scan_trace($this->scan->id, array('last_comment_date_gmt' => $comment->comment_date_gmt));
1164
-
1165
  // Update comments index
1166
  $this->scans->update_scan_trace($this->scan->id, array('comments_index' => $this->scans->get_scan_objects_count($this->scan->id, 'comments')));
1167
-
1168
  // Initialize
1169
  $links_added = array();
1170
  $images_added = array();
1171
  $authors_added = array();
1172
-
1173
  // Retrieve parent permalink
1174
  $parent_url = array('post_id' => $comment->comment_post_ID);
1175
-
1176
  // Process content
1177
  if (!empty($comment->comment_content)) {
1178
-
1179
  // Process links
1180
  if (in_array('links', $this->scan->link_types)) {
1181
  $links = $this->extract_links($comment->comment_content, $parent_url, $comment->comment_ID, 'comments', "", 'comment_content', $comment->comment_date_gmt);
1182
- if (!empty($links))
1183
  $links_added = $this->save($links, $comment->comment_post_ID);
 
1184
  }
1185
-
1186
  // Process images
1187
  if (in_array('images', $this->scan->link_types)) {
1188
  $images = $this->extract_images($comment->comment_content, $parent_url, $comment->comment_ID, 'comments', "", 'comment_content', $comment->comment_date_gmt);
1189
- if (!empty($images))
1190
  $images_added = $this->save($images, $comment->comment_post_ID);
 
1191
  }
1192
  }
1193
-
1194
  // Process author URL
1195
  if (!empty($comment->comment_author_url) && in_array('links', $this->scan->link_types)) {
1196
-
1197
  // Check URL
1198
  $urlinfo = $this->urlo->parse($comment->comment_author_url, $parent_url);
1199
  if ($this->filter_include_urls($urlinfo['url']) && $this->filter_exclude_urls($urlinfo['url'])) {
1200
-
1201
  // Check anchor
1202
  if ($this->filter_anchor_text($comment->comment_author)) {
1203
-
1204
  // Create link array
1205
  $link = array_merge($urlinfo, array(
1206
  'anchor' => $comment->comment_author,
@@ -1211,49 +1260,52 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1211
  'object_field' => 'comment_author_url',
1212
  'object_date_gmt' => $comment->comment_date_gmt,
1213
  ));
1214
-
1215
  // Author links
1216
  $authors_added = $this->save(array($link), $comment->comment_post_ID);
1217
  }
1218
  }
1219
  }
1220
-
1221
  // Update stats for summary
1222
  if (!empty($links_added) || !empty($images_added) || !empty($authors_added)) {
1223
-
1224
  // Update URLs phases
1225
  $this->scans->set_scan_summary_urls_phases($this->scan->id);
1226
-
1227
  // Update objects matched
1228
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'comments');
1229
-
1230
  // Totals of content for each URL status added
1231
  $added = array_unique(array_merge($links_added, $images_added, $authors_added));
1232
- foreach ($added as $url_id)
1233
  $this->scans->set_scan_url_status_total_content($url_id, $this->scan->id);
1234
-
 
1235
  // Check inspect data
1236
- if ($this->inspect())
1237
  return false;
 
1238
  }
1239
-
1240
  // Empty
1241
  } elseif ($this->scans->get_scan_objects_count($this->scan->id, 'comments') >= $this->total_comments) {
1242
-
1243
  // Update populated status
1244
  $this->scans->update_scan_trace($this->scan->id, array('populated_comments' => true));
1245
-
1246
  // Check inspect data
1247
- if ($this->inspect())
1248
  return false;
1249
-
 
1250
  // Check data to inspect
1251
  } elseif ($this->inspect()) {
1252
-
1253
  // Working
1254
  return false;
1255
  }
1256
-
1257
  // End or next comment
1258
  return $this->scans->get_scan_trace($this->scan->id, 'populated_comments')? true : $this->content_comments();
1259
  }
@@ -1264,50 +1316,53 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1264
  * Retrieve next comment
1265
  */
1266
  private function content_comments_next($exceptions = array()) {
1267
-
1268
  // Globals
1269
  global $wpdb;
1270
-
1271
  // Initialize
1272
  $where = '1 = 1';
1273
-
1274
  // Check exceptions
1275
- if (!empty($exceptions))
1276
  $where .= ' AND comment_ID NOT IN ('.implode(',', array_map('intval', $exceptions)).')';
1277
-
 
1278
  // Check last date condition
1279
  $last_date_gmt = $this->scans->get_scan_trace($this->scan->id, 'last_comment_date_gmt');
1280
- if (!empty($last_date_gmt))
1281
  $where .= ' AND comment_date_gmt '.(('asc' == $this->scan->crawl_order)? '>=' : '<=').' "'.esc_sql($last_date_gmt).'"';
1282
-
 
1283
  // Set arguments
1284
  $this->set_comment_args();
1285
-
1286
  // Retrieve next comment
1287
  $comment = $wpdb->get_row('SELECT comment_ID, comment_post_ID, comment_content, comment_author, comment_author_url, comment_date_gmt FROM '.$wpdb->comments.' WHERE '.$where.' '.$this->comment_args['comment_status'].$this->comment_args['time_scope'].$this->comment_args['content_filters'].' ORDER BY '.$this->comment_args['order_by'].' LIMIT 1');
1288
-
1289
  // Check if comment id previously registered
1290
  if (!empty($comment) && $this->scans->scan_object_exists($this->scan->id, $comment->comment_ID, 'comments')) {
1291
-
1292
  // Prepare identifiers
1293
  $ids = array($comment->comment_ID);
1294
-
1295
  // Check same value of last date
1296
  if ($comment->comment_date_gmt == $last_date_gmt) {
1297
-
1298
  // Check more identifiers with same date
1299
  $existing_ids = $this->scans->get_scan_objects_ids_by_date($this->scan->id, 'comments', $last_date_gmt);
1300
- if (!empty($existing_ids) && is_array($existing_ids))
1301
  $ids = array_unique(array_merge($ids, $existing_ids));
 
1302
  }
1303
-
1304
  // Add exceptions
1305
  $exceptions = empty($exceptions)? $ids : array_unique(array_merge($exceptions, $ids));
1306
-
1307
  // Next comment with exceptions
1308
  $comment = $this->content_comments_next($exceptions);
1309
  }
1310
-
1311
  // Done
1312
  return empty($comment)? false : $comment;
1313
  }
@@ -1318,7 +1373,7 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1318
  * Obtains and process links from the blogroll
1319
  */
1320
  private function content_blogroll() {
1321
-
1322
  // Recursion limit
1323
  static $recursion;
1324
  $recursion = isset($recursion)? 1 : $recursion + 1;
@@ -1326,37 +1381,38 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1326
  $this->restart();
1327
  return false;
1328
  }
1329
-
1330
  // Content max pack
1331
  $this->pack_index++;
1332
  if ($this->pack_index > wplnst_get_nsetting('max_pack')) {
1333
  $this->restart();
1334
  return false;
1335
  }
1336
-
1337
  // Check next blogroll link
1338
  if (false !== ($blogroll_link = $this->content_blogroll_next())) {
1339
-
1340
  // Register object
1341
- if (!$this->scans->register_scan_object($this->scan->id, $blogroll_link->link_id, 'blogroll'))
1342
  return $this->content_blogroll();
1343
-
 
1344
  // Update last blogroll id
1345
  $this->scans->update_scan_trace($this->scan->id, array('last_blogroll_id' => $blogroll_link->link_id));
1346
-
1347
  // Update blogroll index
1348
  $this->scans->update_scan_trace($this->scan->id, array('blogroll_index' => $this->scans->get_scan_objects_count($this->scan->id, 'blogroll')));
1349
-
1350
  // Process link URL
1351
  if (!empty($blogroll_link->link_url)) {
1352
-
1353
  // Check URL
1354
  $urlinfo = $this->urlo->parse($blogroll_link->link_url);
1355
  if ($this->filter_include_urls($urlinfo['url']) && $this->filter_exclude_urls($urlinfo['url'])) {
1356
-
1357
- // Check anchor
1358
  if ($this->filter_anchor_text($blogroll_link->link_name)) {
1359
-
1360
  // Create link array
1361
  $link = array_merge($urlinfo, array(
1362
  'anchor' => $blogroll_link->link_name,
@@ -1367,44 +1423,47 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1367
  'object_field' => 'link_url',
1368
  'object_date_gmt' => '0000-00-00 00:00:00',
1369
  ));
1370
-
1371
  // Add blogroll link
1372
  $blogroll_added = $this->save(array($link));
1373
-
1374
  // Update URLs phases
1375
  $this->scans->set_scan_summary_urls_phases($this->scan->id);
1376
-
1377
  // Update objects matched
1378
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'blogroll');
1379
-
1380
  // Totals of content for each URL status added
1381
- foreach ($blogroll_added as $url_id)
1382
  $this->scans->set_scan_url_status_total_content($url_id, $this->scan->id);
1383
-
 
1384
  // Check inspect data
1385
- if ($this->inspect())
1386
  return false;
 
1387
  }
1388
  }
1389
  }
1390
-
1391
  // Empty
1392
  } elseif ($this->scans->get_scan_objects_count($this->scan->id, 'blogroll') >= $this->total_blogroll) {
1393
-
1394
  // Update populated status
1395
  $this->scans->update_scan_trace($this->scan->id, array('populated_blogroll' => true));
1396
-
1397
  // Check inspect data
1398
- if ($this->inspect())
1399
  return false;
1400
-
 
1401
  // Check data to inspect
1402
  } elseif ($this->inspect()) {
1403
-
1404
  // Working
1405
  return false;
1406
  }
1407
-
1408
  // End or next blogroll link
1409
  return $this->scans->get_scan_trace($this->scan->id, 'populated_blogroll')? true : $this->content_blogroll();
1410
  }
@@ -1415,34 +1474,36 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1415
  * Retrieve next blogroll link
1416
  */
1417
  private function content_blogroll_next($exceptions = array()) {
1418
-
1419
  // Globals
1420
  global $wpdb;
1421
-
1422
  // Initialize
1423
  $where = '1 = 1';
1424
-
1425
  // Check exceptions
1426
- if (!empty($exceptions))
1427
  $where .= ' AND link_id NOT IN ('.implode(',', array_map('intval', $exceptions)).')';
1428
-
 
1429
  // Check last identifier condition
1430
  $last_id = (int) $this->scans->get_scan_trace($this->scan->id, 'last_blogroll_id');
1431
- if (!empty($last_id))
1432
  $where .= ' AND link_id '.(('asc' == $this->scan->crawl_order)? '>' : '<').' '.$last_id;
 
1433
 
1434
  // Set arguments
1435
  $this->set_blogroll_args();
1436
-
1437
  // Query next blogroll link
1438
  $bookmark = $wpdb->get_row('SELECT link_id, link_url, link_name FROM '.$wpdb->links.' WHERE '.$where.' ORDER BY '.$this->blogroll_args['order_by'].' LIMIT 1');
1439
-
1440
  // Check if bookmark is previously registered
1441
  if (!empty($bookmark) && $this->scans->scan_object_exists($this->scan->id, $bookmark->link_id, 'blogroll')) {
1442
  $exceptions[] = $bookmark->link_id;
1443
  $bookmark = $this->content_blogroll_next($exceptions);
1444
  }
1445
-
1446
  // Done
1447
  return empty($bookmark)? false : $bookmark;
1448
  }
@@ -1453,43 +1514,48 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1453
  * Extract links from content
1454
  */
1455
  private function extract_links($content, $parent_url, $object_id, $object_type, $object_post_type, $object_field, $object_date_gmt) {
1456
-
1457
  // Initialize
1458
  $links = array();
1459
-
1460
  // Check links
1461
  if (preg_match_all('/(<a[^>]+href=["|\'](.+)["|\'][^>]*>)(.*)<\/a>/isUu', $content, $matches, PREG_SET_ORDER) > 0) {
1462
-
1463
  // Enum matched links tags
1464
  foreach ($matches as $match) {
1465
-
1466
  // Skip page anchor
1467
- if ('#' == mb_substr($match[2], 0, 1))
1468
  continue;
1469
-
 
1470
  // Check anchor
1471
  $anchor = $match[3];
1472
- if (!$this->filter_anchor_text($anchor))
1473
  continue;
1474
-
 
1475
  // Check URL
1476
  $urlinfo = $this->urlo->parse($match[2], $parent_url);
1477
- if (!$this->filter_include_urls($urlinfo['url']) || !$this->filter_exclude_urls($urlinfo['url']))
1478
  continue;
1479
-
 
1480
  // Check attributes
1481
  $attributes = $this->urlo->extract_attributes($match[1]);
1482
- if (!$this->filter_html_attributes('a', $attributes))
1483
  continue;
1484
-
 
1485
  // Check nofollow
1486
  $nofollow = false;
1487
  if (!empty($attributes['rel'])) {
1488
  $values = explode(' ', strtolower(str_replace("\n", ' ', str_replace("\r", ' ', $attributes['rel']))));
1489
- if (in_array('nofollow', $values))
1490
  $nofollow = true;
 
1491
  }
1492
-
1493
  // Add item
1494
  $links[] = array_merge($urlinfo, array(
1495
  'chunk' => $match[0],
@@ -1505,7 +1571,7 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1505
  ));
1506
  }
1507
  }
1508
-
1509
  // Done
1510
  return $links;
1511
  }
@@ -1516,30 +1582,33 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1516
  * Extract images from content
1517
  */
1518
  private function extract_images($content, $parent_url, $object_id, $object_type, $object_post_type, $object_field, $object_date_gmt) {
1519
-
1520
  // Initialize
1521
  $images = array();
1522
-
1523
  // Check links
1524
  if (preg_match_all('/<img[^>]+src=["|\'](.+)["|\'][^>]*>/isUu', $content, $matches, PREG_SET_ORDER) > 0) {
1525
-
1526
  // Enum matched links tags
1527
  foreach ($matches as $match) {
1528
-
1529
  // Skip page anchor
1530
- if ('#' == mb_substr($match[1], 0, 1))
1531
  continue;
1532
-
 
1533
  // Check URL
1534
  $urlinfo = $this->urlo->parse($match[1], $parent_url);
1535
- if (!$this->filter_include_urls($urlinfo['url']) || !$this->filter_exclude_urls($urlinfo['url']))
1536
  continue;
1537
-
 
1538
  // Check attributes
1539
  $attributes = $this->urlo->extract_attributes($match[0]);
1540
- if (!$this->filter_html_attributes('img', $attributes))
1541
  continue;
1542
-
 
1543
  // Add item
1544
  $images[] = array_merge($urlinfo, array(
1545
  'chunk' => $match[0],
@@ -1553,7 +1622,7 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1553
  ));
1554
  }
1555
  }
1556
-
1557
  // Done
1558
  return $images;
1559
  }
@@ -1569,109 +1638,119 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1569
  * Check if passes anchor text filters
1570
  */
1571
  private function filter_anchor_text($anchor) {
1572
-
1573
  // Check filters
1574
- if (empty($this->scan->anchor_filters))
1575
  return true;
1576
-
 
1577
  // Initialize
1578
  $passed = array();
1579
-
1580
  // Version without tags
1581
  $anchor_text = strip_tags($anchor);
1582
-
1583
  // Enum filters
1584
  foreach ($this->scan->anchor_filters as $filter) {
1585
-
1586
  // Check filter
1587
- if (empty($filter['type']) || !isset($filter['value']))
1588
  continue;
1589
-
 
1590
  // Check if contains a value
1591
  if ('contains' == $filter['type']) {
1592
-
1593
  // Continue if passed
1594
- if (isset($passed['contains']) && true === $passed['contains'])
1595
  continue;
1596
-
 
1597
  // Check tag in filter
1598
  $is_filter_tag = (false !== strpos($filter['value'], '<') || false !== strpos($filter['value'], '>'));
1599
-
1600
  // Test
1601
  $passed['contains'] = (false !== stripos($anchor_text, $filter['value'])) || ($is_filter_tag && false !== stripos($anchor, $filter['value']));
1602
-
1603
  // Check if not contain a value
1604
  } elseif ('not-contains' == $filter['type']) {
1605
-
1606
  // Continue if passed
1607
- if (isset($passed['contains']) && false === $passed['contains'])
1608
  continue;
1609
-
 
1610
  // Check tag in filter
1611
  $is_filter_tag = (false !== strpos($filter['value'], '<') || false !== strpos($filter['value'], '>'));
1612
-
1613
  // Test
1614
  $passed['not-contains'] = (false === stripos($anchor_text, $filter['value'])) || ($is_filter_tag && false === stripos($anchor, $filter['value']));
1615
-
1616
  // Check if equal to a value
1617
  } elseif ('equal-to' == $filter['type']) {
1618
-
1619
  // Continue if passed
1620
- if (isset($passed['equal-to']) && true === $passed['equal-to'])
1621
  continue;
1622
-
 
1623
  // Test
1624
  $passed['equal-to'] = ($anchor == $filter['value']);
1625
-
1626
  // Check if not equal to a value
1627
  } elseif ('not-equal-to' == $filter['type']) {
1628
-
1629
  // Continue if passed
1630
- if (isset($passed['not-equal-to']) && false === $passed['not-equal-to'])
1631
  continue;
1632
-
 
1633
  // Test
1634
  $passed['not-equal-to'] = ($anchor != $filter['value']);
1635
-
1636
  // Check if begins with value
1637
  } elseif ('begins-with' == $filter['type']) {
1638
-
1639
  // Continue if passed
1640
- if (isset($passed['begins-with']) && true === $passed['begins-with'])
1641
  continue;
1642
-
 
1643
  // Test
1644
  $passed['begins-with'] = (0 === stripos($anchor, $filter['value']));
1645
-
1646
  // Check if ends with value
1647
  } elseif ('ends-by' == $filter['type']) {
1648
-
1649
  // Continue if passed
1650
- if (isset($passed['ends-by']) && true === $passed['ends-by'])
1651
  continue;
1652
-
 
1653
  // Test
1654
  $passed['ends-by'] = (($temp = strlen($anchor) - strlen($filter['value'])) >= 0 && stripos($anchor, $filter['value'], $temp) !== false);
1655
-
1656
  // Check if is empty
1657
  } elseif ('empty' == $filter['type']) {
1658
-
1659
  // Continue if passed
1660
- if (isset($passed['empty']))
1661
  continue;
1662
-
 
1663
  // Test
1664
  $passed['empty'] = ($anchor === '');
1665
  }
1666
  }
1667
-
1668
  // Check filters
1669
  $checks = array('contains', 'not-contains', 'equal-to', 'not-equal', 'begins-with', 'ends-by', 'empty');
1670
  foreach ($checks as $check) {
1671
- if (isset($passed[$check]) && false === $passed[$check])
1672
  return false;
 
1673
  }
1674
-
1675
  // Done
1676
  return true;
1677
  }
@@ -1682,70 +1761,77 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1682
  * Filter for URL including
1683
  */
1684
  private function filter_include_urls($url) {
1685
-
1686
  // Check filters
1687
- if (empty($this->scan->include_urls))
1688
  return true;
1689
-
 
1690
  // Initialize
1691
  $passed = array();
1692
-
1693
  // Enum filters
1694
  foreach ($this->scan->include_urls as $filter) {
1695
-
1696
  // Check filter
1697
- if (empty($filter['type']) || !isset($filter['value']))
1698
  continue;
1699
-
 
1700
  // Check if match all value
1701
  if ('full-url' == $filter['type']) {
1702
-
1703
  // Continue if passed
1704
- if (isset($passed['full-url']) && true === $passed['full-url'])
1705
  continue;
1706
-
 
1707
  // Test
1708
  $passed['full-url'] = ($url == $filter['value']);
1709
-
1710
  // Check if match a value
1711
  } elseif ('matched-string' == $filter['type']) {
1712
-
1713
  // Continue if passed
1714
- if (isset($passed['matched-string']) && true === $passed['matched-string'])
1715
  continue;
1716
-
 
1717
  // Test
1718
  $passed['matched-string'] = (false !== stripos($url, $filter['value']));
1719
-
1720
  // Check if is prefixed
1721
  } elseif ('url-prefix' == $filter['type']) {
1722
-
1723
  // Continue if passed
1724
- if (isset($passed['url-prefix']) && true === $passed['url-prefix'])
1725
  continue;
1726
-
 
1727
  // Test
1728
  $passed['url-prefix'] = (0 === stripos($url, $filter['value']));
1729
-
1730
  // Check if ends with value
1731
  } elseif ('url-suffix' == $filter['type']) {
1732
-
1733
  // Continue if passed
1734
- if (isset($passed['url-suffix']) && true === $passed['url-suffix'])
1735
  continue;
1736
-
 
1737
  // Test
1738
  $passed['url-suffix'] = (($temp = strlen($url) - strlen($filter['value'])) >= 0 && stripos($url, $filter['value'], $temp) !== false);
1739
  }
1740
  }
1741
-
1742
  // Check filters
1743
  $checks = array('full-url', 'matched-string', 'url-prefix', 'url-suffix');
1744
  foreach ($checks as $check) {
1745
- if (isset($passed[$check]) && false === $passed[$check])
1746
  return false;
 
1747
  }
1748
-
1749
  // Done
1750
  return true;
1751
  }
@@ -1756,70 +1842,77 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1756
  * Filter for URL excluding
1757
  */
1758
  private function filter_exclude_urls($url) {
1759
-
1760
  // Check filters
1761
- if (empty($this->scan->exclude_urls))
1762
  return true;
1763
-
 
1764
  // Initialize
1765
  $passed = array();
1766
-
1767
  // Enum filters
1768
  foreach ($this->scan->exclude_urls as $filter) {
1769
-
1770
  // Check filter
1771
- if (empty($filter['type']) || !isset($filter['value']))
1772
  continue;
1773
-
 
1774
  // Check if match all value
1775
  if ('full-url' == $filter['type']) {
1776
-
1777
  // Continue if passed
1778
- if (isset($passed['full-url']) && false === $passed['full-url'])
1779
  continue;
1780
-
 
1781
  // Test
1782
  $passed['full-url'] = ($url != $filter['value']);
1783
-
1784
  // Check if match a value
1785
  } elseif ('matched-string' == $filter['type']) {
1786
-
1787
  // Continue if passed
1788
- if (isset($passed['matched-string']) && false === $passed['matched-string'])
1789
  continue;
1790
-
 
1791
  // Test
1792
  $passed['matched-string'] = (false === stripos($url, $filter['value']));
1793
-
1794
  // Check if is prefixed
1795
  } elseif ('url-prefix' == $filter['type']) {
1796
-
1797
  // Continue if passed
1798
- if (isset($passed['url-prefix']) && false === $passed['url-prefix'])
1799
  continue;
1800
-
 
1801
  // Test
1802
  $passed['url-prefix'] = (0 !== stripos($url, $filter['value']));
1803
-
1804
  // Check if ends with value
1805
  } elseif ('url-suffix' == $filter['type']) {
1806
-
1807
  // Continue if passed
1808
- if (isset($passed['url-suffix']) && false === $passed['url-suffix'])
1809
  continue;
1810
-
 
1811
  // Test
1812
  $passed['url-suffix'] = (($temp = strlen($url) - strlen($filter['value'])) >= 0 && stripos($url, $filter['value'], $temp) === false);
1813
  }
1814
  }
1815
-
1816
  // Check filters
1817
  $checks = array('full-url', 'matched-string', 'url-prefix', 'url-suffix');
1818
  foreach ($checks as $check) {
1819
- if (isset($passed[$check]) && false === $passed[$check])
1820
  return false;
 
1821
  }
1822
-
1823
  // Done
1824
  return true;
1825
  }
@@ -1830,127 +1923,137 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1830
  * Filter based on attributes
1831
  */
1832
  private function filter_html_attributes($element, $attributes) {
1833
-
1834
  // Check filters
1835
- if (empty($this->scan->html_attributes))
1836
  return true;
1837
-
 
1838
  // Initialize
1839
  $passed = array();
1840
-
1841
  // Isolate attributes
1842
  $att_names = array_keys($attributes);
1843
-
1844
  // Enum filters
1845
  foreach ($this->scan->html_attributes as $filter) {
1846
-
1847
  // Check filter
1848
- if (empty($filter['element']) || $element != $filter['element'] || !isset($filter['att']) || empty($filter['having']))
1849
  continue;
1850
-
 
1851
  // Check if not have an attribute
1852
  if ('not-have' == $filter['having']) {
1853
-
1854
  // Continue if not passed
1855
- if (isset($passed['not-have']) && false === $passed['not-have'])
1856
  continue;
1857
-
 
1858
  // Test
1859
  $passed['not-have'] = !in_array($filter['att'], $att_names);
1860
-
1861
  // Contains
1862
  } elseif ('contains' == $filter['op']) {
1863
-
1864
  // Continue if passed
1865
- if (isset($passed['contains']) && true === $passed['contains'])
1866
  continue;
1867
-
 
1868
  // Need a filter value
1869
  if (!isset($filter['value']) || '' === ''.trim($filter['value'])) {
1870
  $passed['contains'] = false;
1871
  continue;
1872
  }
1873
-
1874
  // Check att name compatibility
1875
  if (!in_array($filter['att'], $att_names)) {
1876
  $passed['contains'] = false;
1877
  continue;
1878
  }
1879
-
1880
  // Final test
1881
  $passed['contains'] = in_array(strtolower($filter['value']), $att_values)? $filter['value'] : false;
1882
-
1883
  // Not contains
1884
  } elseif ('not-contains' == $filter['op']) {
1885
-
1886
  // Continue if passed
1887
- if (isset($passed['not-contains']) && true === $passed['not-contains'])
1888
  continue;
1889
-
 
1890
  // Need a filter value
1891
  if (!isset($filter['value']) || '' === ''.trim($filter['value'])) {
1892
  $passed['not-contains'] = false;
1893
  continue;
1894
  }
1895
-
1896
  // Check att name compatibility
1897
  if (!in_array($filter['att'], $att_names)) {
1898
  $passed['not-contains'] = false;
1899
  continue;
1900
  }
1901
-
1902
  // Final test
1903
  $passed['not-contains'] = !in_array(strtolower($filter['value']), $att_values)? $filter['value'] : false;
1904
-
1905
  // Equal
1906
  } elseif ('equal' == $filter['op']) {
1907
-
1908
  // Continue if passed
1909
- if (isset($passed['equal']) && true === $passed['equal'])
1910
  continue;
1911
-
 
1912
  // Test
1913
  $passed['equal'] = in_array($filter['att'], $att_names)? ($attributes[$filter['att']] == (isset($filter['value'])? $filter['value'] : '')) : false;
1914
-
1915
  // Not equal
1916
  } elseif ('not-equal' == $filter['op']) {
1917
-
1918
  // Continue if passed
1919
- if (isset($passed['not-equal']) && false === $passed['not-equal'])
1920
  continue;
1921
-
 
1922
  // Test
1923
  $passed['not-equal'] = in_array($filter['att'], $att_names)? ($attributes[$filter['att']] != (isset($filter['value'])? $filter['value'] : '')) : false;
1924
-
1925
  // Not empty value
1926
  } elseif ('not-empty' == $filter['op']) {
1927
-
1928
  // Continue if passed
1929
- if (isset($passed['not-empty']) && false === $passed['not-empty'])
1930
  continue;
1931
-
 
1932
  // Test
1933
  $passed['not-empty'] = in_array($filter['att'], $att_names)? ($attributes[$filter['att']] !== '') : false;
1934
-
1935
  // Empty value
1936
  } elseif ('empty' == $filter['op']) {
1937
-
1938
  // Continue if passed
1939
- if (isset($passed['empty']) && false === $passed['empty'])
1940
  continue;
1941
-
 
1942
  // Test
1943
  $passed['empty'] = in_array($filter['att'], $att_names)? ($attributes[$filter['att']] === '') : false;
1944
  }
1945
  }
1946
-
1947
  // Check filters
1948
  $checks = array('not-have', 'contains', 'not-contains', 'equal', 'not-equal', 'not-empty', 'empty');
1949
  foreach ($checks as $check) {
1950
- if (isset($passed[$check]) && false === $passed[$check])
1951
  return false;
 
1952
  }
1953
-
1954
  // Done
1955
  return true;
1956
  }
@@ -1961,91 +2064,98 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
1961
  * Extract filter content for queries
1962
  */
1963
  private function filter_for_queries() {
1964
-
1965
-
1966
  /* Initialization */
1967
-
1968
  // Check cache
1969
  static $matches;
1970
- if (isset($matches))
1971
  return $matches;
 
1972
  $matches = array();
1973
-
1974
  // Check configuration
1975
- if (!$this->scan->filtered_query)
1976
  return $matches;
1977
-
1978
-
 
1979
  /* Anchor filters */
1980
-
1981
  // Check anchor filters
1982
  if (!empty($this->scan->anchor_filters)) {
1983
-
1984
  // Enum anchor filters
1985
  foreach ($this->scan->anchor_filters as $filter) {
1986
-
1987
  // Check filter
1988
- if (empty($filter['type']) || !isset($filter['value']) || '' === ''.trim($filter['value']))
1989
  continue;
1990
-
 
1991
  // Match filters
1992
  if (in_array($filter['type'], array('contains', 'equal-to', 'begins-with', 'ends-by'))) {
1993
-
1994
  // Need this string
1995
  $matches[] = $filter['value'];
1996
  }
1997
  }
1998
  }
1999
-
2000
-
2001
  /* Include URLs */
2002
-
2003
  // Check include filters
2004
  if (!empty($this->scan->include_urls)) {
2005
-
2006
  // Enum include filters
2007
  foreach ($this->scan->include_urls as $filter) {
2008
-
2009
  // Check filter
2010
- if (empty($filter['type']) || !isset($filter['value']) || '' === ''.trim($filter['value']))
2011
  continue;
2012
-
 
2013
  // Match filters
2014
  if (in_array($filter['type'], array('full-url', 'matched-string', 'url-prefix', 'url-suffix'))) {
2015
-
2016
  // Need this string
2017
  $matches[] = $filter['value'];
2018
  }
2019
  }
2020
  }
2021
-
2022
-
2023
  /* HTML attributes */
2024
-
2025
  // Check attributes filters
2026
  if (!empty($this->scan->html_attributes)) {
2027
-
2028
  // Enum filters
2029
  foreach ($this->scan->html_attributes as $filter) {
2030
-
2031
  // Check filter value
2032
- if (!isset($filter['value']) || '' === ''.trim($filter['value']))
2033
  continue;
2034
-
 
2035
  // Check having and attribute part
2036
- if (empty($filter['having']) || 'have' != $filter['having'] || empty($filter['att']) || '' == 'att'.trim($filter['att']))
2037
  continue;
2038
-
 
2039
  // Check operation
2040
- if (empty($filter['op']) || !in_array($filter['op'], array('contains', 'equal')))
2041
  continue;
2042
-
 
2043
  // Add string
2044
  $matches[] = $filter['value'];
2045
  }
2046
  }
2047
-
2048
-
2049
  // Done
2050
  return $matches;
2051
  }
@@ -2061,59 +2171,63 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
2061
  * Save links
2062
  */
2063
  private function save($links, $parent_post_id = 0) {
2064
-
2065
  // Initialize
2066
  $statuses = array();
2067
-
2068
  // Enum links
2069
  foreach ($links as $link) {
2070
-
2071
  // Avoid empty URLs
2072
- if ('' === ''.trim($link['url']))
2073
  continue;
2074
-
 
2075
  // Malformed links tracking
2076
  if ($link['malformed']) {
2077
- if (!$this->scan->malformed)
2078
  continue;
 
2079
  }
2080
-
2081
  // Search by main URL
2082
  if (false !== ($row = $this->scans->get_scan_url(array('url' => $link['url'], 'no_cache' => true)))) {
2083
  $url_id = $row->url_id;
2084
-
2085
  // Register scan URL
2086
  } elseif (false === ($url_id = $this->scans->add_scan_url($link, $this->scan->id))) {
2087
  continue;
2088
  }
2089
-
2090
  // Check destination type
2091
- if (isset($link['scope']) && in_array($this->scan->destination_type, array('internal', 'external')) && $link['scope'] != $this->scan->destination_type)
2092
  continue;
2093
-
 
2094
  // Save URL location
2095
  $this->scans->add_scan_url_location($url_id, $this->scan->id, $link);
2096
-
2097
  // Check our tiny cache
2098
- if (in_array($url_id, $statuses))
2099
  continue;
2100
-
 
2101
  // Check if exists a previous status identifier
2102
  if (false !== $this->scans->get_scan_url_status(array('url_id' => $url_id, 'scan_id' => $this->scan->id))) {
2103
  $statuses[] = $url_id;
2104
  continue;
2105
  }
2106
-
2107
  // Check phase
2108
  $phase = $this->urlo->is_crawleable($link)? 'wait' : 'end';
2109
-
2110
  // Create URL status
2111
  $this->scans->add_scan_url_status($url_id, $this->scan->id, $phase);
2112
-
2113
  // Status on
2114
  $statuses[] = $url_id;
2115
  }
2116
-
2117
  // Done
2118
  return $statuses;
2119
  }
@@ -2129,16 +2243,18 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
2129
  * Cast relative URLs to absolute
2130
  */
2131
  public function parent_permalink($parent) {
2132
-
2133
  // Check array
2134
- if (!is_array($parent) || !isset($parent['post_id']))
2135
  return false;
2136
-
 
2137
  // Check identifier
2138
  $post_id = (int) $parent['post_id'];
2139
- if (empty($post_id))
2140
  return false;
2141
-
 
2142
  // Return permalink
2143
  return $this->get_permalink($post_id);
2144
  }
@@ -2151,22 +2267,24 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
2151
  * so we use the short permalink form to catch the redirection.
2152
  */
2153
  private function get_permalink($post_id) {
2154
-
2155
  // Permalinks cache
2156
  static $permalinks;
2157
- if (!isset($permalinks))
2158
  $permalinks = array();
2159
-
 
2160
  // Check cache
2161
- if (isset($permalinks[$post_id]))
2162
  return $permalinks[$post_id];
2163
-
 
2164
  // Initialize
2165
  $permalinks[$post_id] = false;
2166
-
2167
  // Load cURL wrapper library
2168
  wplnst_require('core', 'curl');
2169
-
2170
  // cURL request
2171
  $response = WPLNST_Core_CURL::request(array(
2172
  'CURLOPT_URL' => $this->urlo->home_url.'/?p='.$post_id,
@@ -2180,41 +2298,45 @@ class WPLNST_Core_Crawler extends WPLNST_Core_Module {
2180
  'CURLOPT_TIMEOUT' => $this->request_timeout,
2181
  'CURLOPT_USERAGENT' => wplnst_get_tsetting('user_agent'),
2182
  ));
2183
-
2184
  // Check response
2185
- if ($response['error'])
2186
  return false;
 
2187
 
2188
  // Check response
2189
  $data = trim($response['data']);
2190
- if (empty($data))
2191
  return false;
2192
-
 
2193
  // Enum response links
2194
  $data = explode("\n", $data);
2195
  foreach ($data as $line) {
2196
-
2197
  // Clear line
2198
  $line = trim(preg_replace('/\s+/', ' ', $line));
2199
-
2200
  // Check redirection in status code
2201
  if (!isset($status_code) && 0 === stripos($line, 'HTTP/')) {
2202
  $line = explode(' ', $line);
2203
  if (count($line) > 1) {
2204
  $status_code = trim($line[1]);
2205
- if ('30' != mb_substr($status_code, 0, 2))
2206
  return false;
 
2207
  }
2208
-
2209
  // Check Location
2210
  } elseif (isset($status_code) && 0 === stripos($line, 'location:')) {
2211
  $location = trim(mb_substr($line, 9));
2212
  $parts = @parse_url($location);
2213
- if (!empty($parts['scheme']) && !empty($parts['host']))
2214
  $permalinks[$post_id] = $location;
 
2215
  }
2216
  }
2217
-
2218
  // Done
2219
  return $permalinks[$post_id];
2220
  }
4
  require_once(dirname(__FILE__).'/module.php');
5
 
6
  /**
7
+ * Crawler class
8
  *
9
  * @package WP Link Status
10
+ * @subpackage Core
11
  */
12
  class WPLNST_Core_Crawler extends WPLNST_Core_Module {
13
 
91
  * Custom constructor
92
  */
93
  protected function on_construct($args = null) {
94
+
95
  // Check scan argument
96
  $scan_id = empty($args['scan_id'])? 0 : (int) $args['scan_id'];
97
+ if (empty($scan_id)) {
98
  return;
99
+ }
100
+
101
  // Check thread argument
102
  $this->thread_id = empty($args['thread_id'])? 0 : (int) $args['thread_id'];
103
+ if (empty($this->thread_id)) {
104
  return;
105
+ }
106
+
107
  // Crawler URL argument
108
  $this->crawler_url = empty($args['crawler_url'])? false : $args['crawler_url'];
109
+ if (empty($this->crawler_url)) {
110
  return;
111
+ }
112
+
113
  // Check scan record
114
+ if (false === ($this->scan = $this->get_scan_by_id($scan_id))) {
115
  return;
116
+ }
117
 
118
  // Debug point
119
  $this->debug('__construct');
120
+
121
  // URL object
122
  $this->load_url_object();
123
+
124
  // All timeouts
125
  $this->set_timeouts();
126
+
127
  // Incoming POST request data
128
+ if (!empty($_POST['url_id'])) {
129
  $this->request();
130
+ }
131
+
132
  // Check waiting links before next content data
133
+ if (!$this->inspect()) {
134
  $this->content();
135
+ }
136
  }
137
 
138
 
150
  // Local timeouts
151
  $this->connect_timeout = wplnst_get_nsetting('connect_timeout', $this->scan->threads->connect_timeout);
152
  $this->request_timeout = wplnst_get_nsetting('request_timeout', $this->scan->threads->request_timeout);
153
+
154
  // Timeouts sum and extra
155
  $this->total_timeout = $this->connect_timeout + $this->request_timeout + wplnst_get_nsetting('extra_timeout');
156
  }
161
  * Result from a external request
162
  */
163
  private function request() {
164
+
165
  // Debug point
166
  $this->debug('request');
167
+
168
  // Check URL id
169
  $url_id = (int) $_POST['url_id'];
170
+ if (empty($url_id)) {
171
  return;
172
+ }
173
+
174
  // Check URL record
175
+ if (false === ($url = $this->scans->get_scan_url(array('id' => $url_id, 'no_cache' => true)))) {
176
  return;
177
+ }
178
+
179
  // Check URL status record
180
+ if (false === ($rows = $this->scans->get_scan_url_status(array('url_id' => $url_id, 'scan_id' => $this->scan->id, 'no_cache' => true)))) {
181
  return;
182
+ }
183
+
184
  // Check URL status phase
185
+ if (1 != count($rows) || in_array($rows[0]->phase, array('end', 'discard', 'failed'))) {
186
  return;
187
+ }
188
+
189
  // Check redirection mode
190
  $redirection = (!empty($_GET['wplnst_redirection']) && '1' == $_GET['wplnst_redirection']);
191
+
192
  // Analyze request
193
  wplnst_require('core', 'status');
194
  $status = new WPLNST_Core_Status($_POST);
195
 
196
  // Check discarded response
197
  $discard = empty($status->level)? false : (!in_array($status->level, $this->scan->status_levels) && !in_array($status->code, $this->scan->status_codes));
198
+
199
  // Check redirection steps
200
  $redirect_steps = @json_decode($rows[0]->redirect_steps, true);
201
+ if (empty($redirect_steps) || !is_array($redirect_steps)) {
202
  $redirect_steps = array();
203
+ }
204
+
205
  // Normal mode
206
  if (!$this->scan->redir_status || !$redirection) {
207
+
208
  // Check redirection
209
  $phase_next = 'end';
210
  $redirect_url_id = 0;
211
  $redirect_url_status = "";
212
  $redirect_curl_errno = 0;
213
  if ($this->scan->redir_status && !$discard && 3 == $status->level && !empty($status->redirect_url)) {
214
+
215
  // Default redirection
216
  $redirect_url = $status->redirect_url;
217
+
218
  // Analyze
219
  $urlinfo = $this->urlo->parse($redirect_url, $url->url);
220
  if ($this->urlo->is_crawleable($urlinfo)) {
221
+
222
  // Copy final URL
223
  $redirect_url = $urlinfo['url'];
224
+
225
  // Search by main URL
226
  if (false !== ($redir_url = $this->scans->get_scan_url(array('url' => $redirect_url, 'no_cache' => true)))) {
227
+
228
  // Existing URL
229
  $phase_next = 'redir';
230
  $redirect_url_id = $redir_url->url_id;
231
+
232
  // New URL for this scan
233
  } elseif (false !== ($test_url_id = $this->scans->add_scan_url($urlinfo, $this->scan->id))) {
234
+
235
  // Mark to check
236
  $phase_next = 'redir';
237
  $redirect_url_id = $test_url_id;
238
  }
239
  }
240
+
241
  // Add possible fragment to save "As is"
242
  $redirect_url .= $urlinfo['fragment'];
243
  }
244
+
245
  // Update status data
246
  $this->scans->update_scan_url_status($url_id, $this->scan->id, array(
247
  'phase' => $discard? 'discard' : $phase_next,
259
  'curl_errno' => $discard? 0 : $status->curl_errno,
260
  'requests' => $discard? 0 : (int) $rows[0]->requests + 1,
261
  ));
262
+
263
  // Update URL data
264
  $this->scans->update_scan_url($url_id, array(
265
  'last_scan_id' => $this->scan->id,
268
  'last_curl_errno' => $status->curl_errno,
269
  'last_request_at' => $status->request_at,
270
  ));
271
+
272
  // Is Redirection
273
  } else {
274
+
275
  // Prepare update
276
  $update = array(
277
  'phase' => 'end',
279
  'redirect_curl_errno' => $status->curl_errno,
280
  'requests' => (int) $rows[0]->requests + 1,
281
  );
282
+
283
  // Check new redirection
284
  if (empty($curl_errno) && 3 == $status->level && !empty($status->redirect_url) && ($rows[0]->requests + 1) <= wplnst_get_nsetting('max_redirs')) {
285
+
286
  // Check crawleable
287
  $urlinfo = $this->urlo->parse($status->redirect_url, $url->url);
288
  if ($this->urlo->is_crawleable($urlinfo)) {
289
+
290
  // Search by main URL
291
  if (false !== ($redir_url = $this->scans->get_scan_url(array('url' => $urlinfo['url'], 'no_cache' => true)))) {
292
+
293
  // Existing URL
294
  $redirect_url_id = $redir_url->url_id;
295
+
296
  // New URL for this scan
297
  } elseif (false !== ($test_url_id = $this->scans->add_scan_url($urlinfo, $this->scan->id))) {
298
+
299
  // Added URL
300
  $redirect_url_id = $test_url_id;
301
  }
302
+
303
  // For existing or correctly added URL
304
  if (!empty($redirect_url_id)) {
305
+
306
  // Copy old steps
307
  $redirect_steps[] = array('url' => $rows[0]->redirect_url, 'status' => $rows[0]->redirect_url_status);
308
+
309
  // New redir
310
  $update['phase'] = 'redir';
311
  $update['redirect_url'] = $urlinfo['url'].$urlinfo['fragment'];
315
  }
316
  }
317
  }
318
+
319
  // Update status data
320
  $this->scans->update_scan_url_status($url_id, $this->scan->id, $update);
321
  }
322
+
323
  // Status codes
324
  $this->scans->set_scan_summary_status_codes($this->scan->id, $this->scan->status_levels, $this->scan->status_codes);
325
+
326
  // URLs summary
327
  $this->scans->set_scan_summary_urls_phases($this->scan->id);
328
  }
344
 
345
  // Check if this scan is playing
346
  if ('play' != $this->scans->get_scan_status($this->scan->id)) {
347
+
348
  // Stopped or ended
349
  return true;
350
+
351
  // Retrieve next URL
352
  } elseif (false !== ($url = $this->inspect_wait())) {
353
+
354
  // Check no playing rows flag, and update started datetime
355
  if (true !== $url && false !== $this->scans->update_scan_url_status($url->url_id, $this->scan->id, array('phase' => 'play', 'started_at' => current_time('mysql', true)))) {
356
+
357
  // Debug point
358
  $this->debug('inspect request');
359
+
360
  // Check Crawler URL in redirection mode
361
  $crawler_url = $this->crawler_url;
362
+ if (isset($url->redirection)) {
363
  $crawler_url = add_query_arg('wplnst_redirection', '1', $crawler_url);
364
+ }
365
+
366
  // Prepare POST fields
367
  $postfields = array(
368
  'url' => $url->url,
372
  'request_timeout' => $this->request_timeout,
373
  'max_download' => wplnst_get_nsetting('max_download') * 1024,
374
  'back_url' => $crawler_url,
 
375
  'user_agent' => wplnst_get_tsetting('user_agent'),
376
  'nonce' => WPLNST_Core_Nonce::create_nonce($url->hash),
377
  );
378
+
379
  // Load cURL wrapper library
380
  wplnst_require('core', 'curl');
381
+
382
  // Spawn crawler call
383
  WPLNST_Core_CURL::spawn(array(
384
  'CURLOPT_URL' => plugins_url('core/requests/http.php', WPLNST_FILE),
387
  'CURLOPT_POSTFIELDS' => http_build_query($postfields, null, '&'),
388
  'CURLOPT_HTTPHEADER' => array('Content-Type: application/x-www-form-urlencoded; charset=utf-8'),
389
  ));
390
+
391
  // Ends here, it's going out to check status
392
  return true;
393
  }
394
+
395
  // Check scan ending from all content
396
  } elseif ($this->content_end()) {
397
 
400
 
401
  // Set "end" scan status
402
  $this->scans->end_scan($this->scan->id);
403
+
404
  // URLs status codes summary
405
  $this->scans->set_scan_summary_status_codes($this->scan->id, $this->scan->status_levels, $this->scan->status_codes, true);
406
+
407
  // URLs phases summary
408
  $this->scans->set_scan_summary_urls_phases($this->scan->id, true);
409
+
410
  // Update posts matched
411
+ if ($this->scan->check_posts) {
412
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'posts', true);
413
+ }
414
+
415
  // Update posts matched
416
+ if ($this->scan->check_comments) {
417
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'comments', true);
418
+ }
419
+
420
  // Update blogroll matched
421
+ if ($this->scan->check_blogroll) {
422
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'blogroll', true);
423
+ }
424
+
425
  // Remove discarded URLS
426
  $this->scans->remove_scan_discard_urls($this->scan->id);
427
+
428
  // Update real total posts
429
+ if ($this->scan->check_posts) {
430
  $this->scans->update_scan_trace($this->scan->id, array('total_posts' => $this->scans->get_scan_objects_count($this->scan->id, 'posts')));
431
+ }
432
+
433
  // Remove registered objects
434
  $this->scans->remove_scan_objects($this->scan->id);
435
+
436
  // Check notifications
437
  if ($this->scan->notify_default || ($this->scan->notify_address && !empty($this->scan->notify_address_email))) {
438
  wplnst_require('core', 'notify');
439
  WPLNST_Core_Notify::completed($this->scan);
440
  }
441
+
442
  // Check for queued scans
443
  $this->activity();
444
+
445
  // The end
446
  return true;
447
  }
448
+
449
  // No wait or play with timeout
450
  return false;
451
  }
456
  * Inspect a waiting url to check
457
  */
458
  private function inspect_wait() {
459
+
460
  // Retrieve next wait
461
+ if (false !== ($url = $this->scans->get_scan_url_waiting($this->scan->id))) {
462
  return $url;
463
+ }
464
+
465
  // Check playing rows
466
+ if (false === ($rows = $this->scans->get_scan_url_status(array('scan_id' => $this->scan->id, 'phase' => 'play', 'no_cache' => true, 'order' => 'started_at ASC')))) {
467
  return false;
468
+ }
469
+
470
  // Max requests allowed
471
  $max_requests = wplnst_get_nsetting('max_requests');
472
+
473
  // Enum playing rows
474
  foreach ($rows as $row) {
475
+
476
  // Check timeouted
477
  if (time() - strtotime($row->started_at.' UTC') > $this->total_timeout) {
478
+
479
  // Check max requests
480
  if ($row->requests >= $max_requests) {
481
+
482
  // Mark as a request phase
483
  $this->scans->update_scan_url_status($url->url_id, $this->scan->id, array('phase' => 'failed'));
484
+
485
  // Retrieve URL
486
  } elseif (false !== ($url = $this->scans->get_scan_url(array('id' => $row->url_id, 'no_cache' => true)))) {
487
+
488
  // Update from play to wait
489
  if (false !== $this->scans->update_scan_url_status($url->url_id, $this->scan->id, array('phase' => 'wait'))) {
490
+
491
  // URLs summary
492
  $this->scans->set_scan_summary_urls_phases($this->scan->id);
493
+
494
  // Done
495
  return $url;
496
  }
497
  }
498
  }
499
  }
500
+
501
  // Playing rows
502
  return false;
503
  }
513
  * Initialize post args
514
  */
515
  private function set_post_args() {
516
+
517
  // Check previous
518
+ if (isset($this->post_args)) {
519
  return;
520
+ }
521
+
522
  // Initialize arguments
523
  $this->post_args = array();
524
+
525
  // Prepare types and status fragments
526
  $this->post_args['post_types'] = (1 == count($this->scan->post_types))? '= "'.esc_sql($this->scan->post_types[0]).'"' : 'IN ("'.implode('", "', array_map('esc_sql', $this->scan->post_types)).'")';
527
  $this->post_args['post_status'] = (1 == count($this->scan->post_status))? '= "'.esc_sql($this->scan->post_status[0]).'"' : 'IN ("'.implode('", "', array_map('esc_sql', $this->scan->post_status)).'")';
528
+
529
  // Time scope argument
530
  $this->post_args['time_scope'] = $this->get_time_scope_arg('post_date_gmt');
531
+
532
  // Check order
533
  $this->post_args['order_by'] = 'post_date_gmt '.(('asc' == $this->scan->crawl_order)? 'ASC' : 'DESC');
534
+
535
  // Filters arguments
536
  $this->post_args['content_filters'] = $this->get_content_filters_arg('post_content');
537
  }
542
  * Initialize comments args
543
  */
544
  private function set_comment_args() {
545
+
546
  // Check previous
547
+ if (isset($this->comment_args)) {
548
  return;
549
+ }
550
+
551
  // Initialize
552
  $this->comment_args = array();
553
+
554
  // Comment status
555
  $comment_types = WPLNST_Core_Types::get_comment_types_values($this->scan->comment_types);
556
  $this->comment_args['comment_status'] = ' AND comment_approved '.((1 == count($comment_types))? '= "'.esc_sql($comment_types[0]).'"' : 'IN ("'.implode('", "', array_map('esc_sql', $comment_types)).'")');
557
+
558
  // Time scope argument
559
  $this->comment_args['time_scope'] = $this->get_time_scope_arg('comment_date_gmt');
560
 
561
  // Filters arguments
562
  $this->comment_args['content_filters'] = $this->get_content_filters_arg('comment_content');
563
+
564
  // Check order
565
  $this->comment_args['order_by'] = 'comment_date_gmt '.(('asc' == $this->scan->crawl_order)? 'ASC' : 'DESC');
566
  }
571
  * Initialize blogroll args
572
  */
573
  private function set_blogroll_args() {
574
+
575
  // Check previous
576
+ if (isset($this->blogroll_args)) {
577
  return;
578
+ }
579
+
580
  // Initialize arguments
581
  $this->blogroll_args = array();
582
+
583
  // Check order
584
  $this->blogroll_args['order_by'] = 'link_id '.(('asc' == $this->scan->crawl_order)? 'ASC' : 'DESC');
585
  }
590
  * Process next post
591
  */
592
  private function content() {
593
+
594
  // Debug point
595
  $this->debug('content');
596
+
597
  // No script timeout
598
  set_time_limit(0);
599
+
600
  // Retrieve trace array
601
  $trace = $this->scans->get_scan_trace($this->scan->id);
602
+
603
  // Initialize process flags
604
  $process_posts = $process_comments = $process_blogroll = false;
605
+
606
+
607
  /* Check content */
608
+
609
  // Check posts
610
  if ($this->scan->check_posts && empty($trace['populated_posts'])) {
611
  $process_posts = true;
612
  $this->content_total('posts');
613
  }
614
+
615
  // Check comments
616
  if ($this->scan->check_comments && empty($trace['populated_comments'])) {
617
  $process_comments = true;
618
+ if (empty($trace['total_comments_check']) || !$process_posts) {
619
  $this->content_total('comments');
620
+ }
621
  }
622
+
623
  // Check blogroll
624
  if ($this->scan->check_blogroll && empty($trace['populated_blogroll'])) {
625
+
626
  // Check links arg, if not update trace
627
  if (!in_array('links', $this->scan->link_types)) {
628
  $this->total_blogroll = 0;
629
  $this->scans->update_scan_trace($this->scan->id, array('populated_blogroll' => true, 'total_blogroll' => 0));
630
+
631
  // Continue
632
  } else {
633
+
634
  // Mark for process
635
  $process_blogroll = true;
636
+
637
  // Check first update
638
+ if (empty($trace['total_blogroll_check']) || (!$process_posts && !$process_comments)) {
639
  $this->content_total('blogroll');
640
+ }
641
  }
642
  }
643
+
644
+
645
  // Common filters
646
  add_filter('wplnst_relative_parent_url', array(&$this, 'parent_permalink'));
647
+
648
+
649
  /* Processing objects */
650
+
651
  // Process posts
652
+ if ($process_posts && !$this->content_posts()) {
653
  return;
654
+ }
655
+
656
  // Process comments
657
+ if ($process_comments && !$this->content_comments()) {
658
  return;
659
+ }
660
+
661
  // Process blogroll
662
+ if ($process_blogroll && !$this->content_blogroll()) {
663
  return;
664
+ }
665
+
666
+
667
  /* External work or run again */
668
+
669
  // More data or restart
670
+ if (!$this->inspect()) {
671
  $this->restart();
672
+ }
673
  }
674
 
675
 
678
  * Check if this is the end of all content types
679
  */
680
  private function content_end() {
681
+
682
  // Initialize
683
  $the_end = true;
684
+
685
  // Check posts
686
+ if ($this->scan->check_posts) {
687
  $the_end = (false !== $this->scans->get_scan_trace($this->scan->id, 'populated_posts'));
688
+ }
689
+
690
  // Check comments
691
+ if ($the_end && $this->scan->check_comments) {
692
  $the_end = (false !== $this->scans->get_scan_trace($this->scan->id, 'populated_comments'));
693
+ }
694
 
695
  // Check blogroll
696
+ if ($the_end && $this->scan->check_blogroll) {
697
  $the_end = (false !== $this->scans->get_scan_trace($this->scan->id, 'populated_blogroll'));
698
+ }
699
+
700
  // Done
701
  return $the_end;
702
  }
707
  * Time scope limits
708
  */
709
  private function get_time_scope_arg($field) {
710
+
711
  // First basic check
712
+ if (empty($this->scan->time_scope) || 'anytime' == $this->scan->time_scope) {
713
  return '';
714
+ }
715
+
716
  // Check real value
717
+ if (!in_array($this->scan->time_scope, array_keys(WPLNST_Core_Types::get_time_scopes()))) {
718
  return '';
719
+ }
720
+
721
  // Yesterday
722
  if ('yesterday' == $this->scan->time_scope) {
723
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-1 days")).'"';
724
+
725
  // From one week ago
726
  } elseif ('7days' == $this->scan->time_scope) {
727
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-7 days")).'"';
728
+
729
  // From 15 days ago
730
  } elseif ('15days' == $this->scan->time_scope) {
731
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-15 days")).'"';
732
+
733
  // From 1 month ago
734
  } elseif ('month' == $this->scan->time_scope) {
735
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-1 months")).'"';
736
+
737
  // From 3 months ago
738
  } elseif ('3months' == $this->scan->time_scope) {
739
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-3 months")).'"';
743
 
744
  } elseif ('year' == $this->scan->time_scope) {
745
  $back_date = ' > "'.gmdate('Y-m-d 00:00:00', strtotime("-1 years")).'"';
746
+
747
  } elseif ('custom' == $this->scan->time_scope) {
748
  // Pending
749
  }
750
+
751
  // Check value and compose subquery
752
  return isset($back_date)? ' AND '.$field.$back_date : '';
753
  }
758
  * Content filters in query
759
  */
760
  private function get_content_filters_arg($field, $op = ' AND ') {
761
+
762
  // Content matches
763
  $matches = $this->filter_for_queries();
764
+ if (empty($matches)) {
765
  return '';
766
+ }
767
+
768
  // Prepare likes
769
  $likes = array();
770
+ foreach ($matches as $match) {
771
  $likes[] = $field.' LIKE "%'.addcslashes($match, '_%\\').'%"';
772
+ }
773
+
774
  // Likes fragment
775
  return $op.((1 == count($likes))? $likes[0] : '('.implode(' OR ', $likes).')');
776
  }
781
  * Update total posts
782
  */
783
  private function content_total($type, $final = false) {
784
+
785
  // Globals
786
  global $wpdb;
787
+
788
  // Retrieve trace array
789
  $trace = $this->scans->get_scan_trace($this->scan->id);
790
+
791
  // Update posts
792
  if ('posts' == $type) {
793
+
794
  // Debug point
795
  $this->debug('content_total posts');
796
+
797
  // Check trace value
798
  $total_posts = empty($trace['total_posts'])? 0 : (int) $trace['total_posts'];
799
+
800
  // Total posts check
801
  $timestamp = empty($trace['total_posts_check'])? false : (int) $trace['total_posts_check'];
802
  if (false === $timestamp || (time() - $timestamp) >= wplnst_get_nsetting('total_objects')) {
803
+
804
  // Debug point
805
  $this->debug('content_total posts update');
806
+
807
  // Mark checked time
808
  $this->scans->update_scan_trace($this->scan->id, array('total_posts_check' => time()));
809
+
810
  // Set filters
811
  $this->set_post_args();
812
+
813
  // Prepare query
814
  $sql = 'SELECT COUNT(*) FROM '.$wpdb->posts.' WHERE post_type '.$this->post_args['post_types'].' AND post_status '.$this->post_args['post_status'].$this->post_args['time_scope'].$this->post_args['content_filters'];
815
+
816
  // Check last date condition
817
  $last_date_gmt = $this->scans->get_scan_trace($this->scan->id, 'last_post_date_gmt');
818
  if (empty($last_date_gmt)) {
819
+
820
  // Total posts without restrictions
821
  $total_posts = (int) $wpdb->get_var($sql);
822
+
823
  // Check
824
  } else {
825
+
826
  // Sum processed and no-processed
827
  $where = ' AND post_date_gmt '.(('asc' == $this->scan->crawl_order)? '>=' : '<=').' "'.esc_sql($last_date_gmt).'"';
828
  $total_posts = (int) $this->scans->get_scan_trace($this->scan->id, 'posts_index') + (int) $wpdb->get_var($sql.$where.' AND ID NOT IN (SELECT object_id FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = '.esc_sql($this->scan->id).' AND object_type = "posts")');
829
  }
830
+
831
  // Update total posts
832
  $this->scans->update_scan_trace($this->scan->id, array('total_posts' => $total_posts));
833
  }
834
+
835
  // Assign results
836
  $this->total_posts = $total_posts;
837
+
838
  // Update total comments
839
  } elseif ('comments' == $type) {
840
+
841
  // Debug point
842
  $this->debug('content_total comments');
843
+
844
  // Check trace value
845
  $total_comments = empty($trace['total_comments'])? 0 : (int) $trace['total_comments'];
846
+
847
  // Total comments check
848
  $timestamp = empty($trace['total_comments_check'])? false : (int) $trace['total_comments_check'];
849
  if (false === $timestamp || (time() - $timestamp) >= wplnst_get_nsetting('total_objects')) {
850
+
851
  // Debug point
852
  $this->debug('content_total comments update');
853
+
854
  // Mark checked time
855
  $this->scans->update_scan_trace($this->scan->id, array('total_comments_check' => time()));
856
+
857
  // Set filters
858
  $this->set_comment_args();
859
+
860
  // Prepare query
861
  $sql = 'SELECT COUNT(*) FROM '.$wpdb->comments.' WHERE 1 = 1 '.$this->comment_args['comment_status'].$this->comment_args['time_scope'].$this->comment_args['content_filters'];
862
+
863
  // Check last date condition
864
  $last_date_gmt = $this->scans->get_scan_trace($this->scan->id, 'last_comment_date_gmt');
865
  if (empty($last_date_gmt)) {
866
+
867
  // Total comments without restrictions
868
  $total_comments = (int) $wpdb->get_var($sql);
869
+
870
  // Check
871
  } else {
872
+
873
  // Sum processed and no-processed
874
  $where = ' AND comment_date_gmt '.(('asc' == $this->scan->crawl_order)? '>=' : '<=').' "'.esc_sql($last_date_gmt).'"';
875
  $total_comments = (int) $this->scans->get_scan_trace($this->scan->id, 'comments_index') + (int) $wpdb->get_var($sql.$where.' AND comment_ID NOT IN (SELECT object_id FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = '.esc_sql($this->scan->id).' AND object_type = "comments")');
876
  }
877
+
878
  // Update total comments
879
  $this->scans->update_scan_trace($this->scan->id, array('total_comments' => $total_comments));
880
  }
881
+
882
  // Assign results
883
  $this->total_comments = $total_comments;
884
+
885
  // Update total blogroll links
886
  } elseif ('blogroll' == $type) {
887
+
888
  // Debug point
889
  $this->debug('content_total blogroll');
890
+
891
  // Check trace value
892
  $total_blogroll = empty($trace['total_blogroll'])? 0 : (int) $trace['total_blogroll'];
893
+
894
  // Total blogroll check
895
  $timestamp = empty($trace['total_blogroll_check'])? false : (int) $trace['total_blogroll_check'];
896
  if (false === $timestamp || (time() - $timestamp) >= wplnst_get_nsetting('total_objects')) {
897
+
898
  // Debug point
899
  $this->debug('content_total blogroll update');
900
+
901
  // Mark checked time
902
  $this->scans->update_scan_trace($this->scan->id, array('total_blogroll_check' => time()));
903
+
904
  // Set filters
905
  $this->set_blogroll_args();
906
+
907
  // Prepare query
908
  $sql = 'SELECT COUNT(*) FROM '.$wpdb->links;
909
+
910
  // Check last identifier condition
911
  $last_id = (int) $this->scans->get_scan_trace($this->scan->id, 'last_blogroll_id');
912
  if (empty($last_id)) {
913
+
914
  // Total blogroll without restrictions
915
  $total_blogroll = (int) $wpdb->get_var($sql);
916
+
917
  // Check
918
  } else {
919
+
920
  // Sum processed and no-processed
921
  $where = ' WHERE link_id '.(('asc' == $this->scan->crawl_order)? '>' : '<').' '.$last_id;
922
  $total_blogroll = (int) $this->scans->get_scan_trace($this->scan->id, 'blogroll_index') + (int) $wpdb->get_var($sql.$where.' AND link_id NOT IN (SELECT object_id FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = '.esc_sql($this->scan->id).' AND object_type = "blogroll")');
923
  }
924
+
925
  // Update total blogroll
926
  $this->scans->update_scan_trace($this->scan->id, array('total_blogroll' => $total_blogroll));
927
  }
928
+
929
  // Assign results
930
  $this->total_blogroll = $total_blogroll;
931
  }
937
  * Obtains and process contents from posts
938
  */
939
  private function content_posts() {
940
+
941
  // Recursion limit
942
  static $recursion;
943
  $recursion = isset($recursion)? 1 : $recursion + 1;
945
  $this->restart();
946
  return false;
947
  }
948
+
949
  // Content max pack
950
  $this->pack_index++;
951
  if ($this->pack_index > wplnst_get_nsetting('max_pack')) {
952
  $this->restart();
953
  return false;
954
  }
955
+
956
  // Check next post
957
  if (false !== ($post = $this->content_posts_next())) {
958
+
959
  // Register object
960
+ if (!$this->scans->register_scan_object($this->scan->id, $post->ID, 'posts', $post->post_date_gmt)) {
961
  return $this->content_posts();
962
+ }
963
+
964
  // Update last date gmt
965
  $this->scans->update_scan_trace($this->scan->id, array('last_post_date_gmt' => $post->post_date_gmt));
966
+
967
  // Update posts index
968
  $this->scans->update_scan_trace($this->scan->id, array('posts_index' => $this->scans->get_scan_objects_count($this->scan->id, 'posts')));
969
+
970
  // Initialize
971
  $links_added = array();
972
  $images_added = array();
973
  $custom_fields_links_added = array();
974
  $custom_fields_images_added = array();
975
+
976
  // Parent permalink reference
977
  $parent_url = array('post_id' => $post->ID);
978
+
979
  // Process content
980
  if (!empty($post->post_content)) {
981
+
982
  // Process links
983
  if (in_array('links', $this->scan->link_types)) {
984
  $links = $this->extract_links($post->post_content, $parent_url, $post->ID, 'posts', $post->post_type, 'post_content', $post->post_date_gmt);
985
+ if (!empty($links)) {
986
  $links_added = $this->save($links, $post->ID);
987
+ }
988
  }
989
+
990
  // Process images
991
  if (in_array('images', $this->scan->link_types)) {
992
  $images = $this->extract_images($post->post_content, $parent_url, $post->ID, 'posts', $post->post_type, 'post_content', $post->post_date_gmt);
993
+ if (!empty($images)) {
994
  $images_added = $this->save($images, $post->ID);
995
+ }
996
  }
997
  }
998
+
999
  // Check custom fields
1000
  if (!empty($this->scan->custom_fields)) {
1001
+
1002
  // Retrieve post custom fields
1003
  $post_metas = $this->scans->get_post_metas($post->ID);
1004
  if (!empty($post_metas) && is_array($post_metas)) {
1005
+
1006
  // First compare field by key
1007
  foreach ($this->scan->custom_fields as $field) {
1008
+
1009
  // Check field
1010
+ if (empty($field['type']) || !isset($field['name'])) {
1011
  continue;
1012
+ }
1013
+
1014
  // Check existing name
1015
  $name = $field['name'];
1016
  if (isset($post_metas[$name])) {
1017
+
1018
  // Check custom field content
1019
  $post_meta = $post_metas[$name];
1020
  if (!empty($post_meta) && is_array($post_meta)) {
1021
+
1022
  // Enum values
1023
  foreach ($post_meta as $meta_id => $value) {
1024
+
1025
  // Sanitize
1026
  $value = trim($value);
1027
+ if (empty($value)) {
1028
  continue;
1029
+ }
1030
+
1031
  // Direct URL
1032
  if ('url' == $field['type']) {
1033
+
1034
  // Check URL
1035
  $urlinfo = $this->urlo->parse($value, $parent_url);
1036
  if ($this->filter_include_urls($urlinfo['url']) && $this->filter_exclude_urls($urlinfo['url'])) {
1037
+
1038
  // Create link array
1039
  $link = array_merge($urlinfo, array(
1040
  'anchor' => '',
1045
  'object_field' => 'custom_field_url_'.$meta_id.'_'.$name,
1046
  'object_date_gmt' => $post->post_date_gmt,
1047
  ));
1048
+
1049
  // Author links
1050
  $custom_fields_links_added = $this->save(array($link), $post->ID);
1051
  }
1052
+
1053
  // HTML
1054
  } else {
1055
+
1056
  // Process links
1057
  if (in_array('links', $this->scan->link_types)) {
1058
  $links = $this->extract_links($value, $parent_url, $post->ID, 'posts', $post->post_type, 'custom_field_html_'.$meta_id.'_'.$name, $post->post_date_gmt);
1059
+ if (!empty($links)) {
1060
  $custom_fields_links_added = $this->save($links, $post->ID);
1061
+ }
1062
  }
1063
+
1064
  // Process images
1065
  if (in_array('images', $this->scan->link_types)) {
1066
  $images = $this->extract_images($value, $parent_url, $post->ID, 'posts', $post->post_type, 'custom_field_html_'.$meta_id.'_'.$name, $post->post_date_gmt);
1067
+ if (!empty($images)) {
1068
  $custom_fields_images_added = $this->save($images, $post->ID);
1069
+ }
1070
  }
1071
  }
1072
  }
1075
  }
1076
  }
1077
  }
1078
+
1079
  // Update stats for summary
1080
  if (!(empty($links_added) && empty($images_added) && empty($custom_fields_links_added) && empty($custom_fields_images_added))) {
1081
+
1082
  // Update URLs phases
1083
  $this->scans->set_scan_summary_urls_phases($this->scan->id);
1084
+
1085
  // Update objects matched
1086
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'posts');
1087
+
1088
  // Totals of content for each URL status added
1089
  $added = array_unique(array_merge($links_added, $images_added, $custom_fields_links_added, $custom_fields_images_added));
1090
+ foreach ($added as $url_id) {
1091
  $this->scans->set_scan_url_status_total_content($url_id, $this->scan->id);
1092
+ }
1093
+
1094
  // Check inspect data
1095
+ if ($this->inspect()) {
1096
  return false;
1097
+ }
1098
  }
1099
+
1100
  // Empty
1101
  } elseif ($this->scans->get_scan_objects_count($this->scan->id, 'posts') >= $this->total_posts) {
1102
+
1103
  // Update populated status
1104
  $this->scans->update_scan_trace($this->scan->id, array('populated_posts' => true));
1105
+
1106
  // Check inspect data
1107
+ if ($this->inspect()) {
1108
  return false;
1109
+ }
1110
+
1111
  // Check data to inspect
1112
  } elseif ($this->inspect()) {
1113
+
1114
  // Working
1115
  return false;
1116
  }
1117
+
1118
  // End or next post
1119
  return $this->scans->get_scan_trace($this->scan->id, 'populated_posts')? true : $this->content_posts();
1120
  }
1125
  * Retrieve next post
1126
  */
1127
  private function content_posts_next($exceptions = array()) {
1128
+
1129
  // Globals
1130
  global $wpdb;
1131
+
1132
  // Initialize
1133
  $where = '1 = 1';
1134
+
1135
+ // Check exceptions
1136
+ if (!empty($exceptions)) {
1137
+ $where .= ' AND ID NOT IN ('.implode(',', array_map('intval', $exceptions)).')';
1138
+ }
1139
+
1140
  // Check last date condition
1141
  $last_date_gmt = $this->scans->get_scan_trace($this->scan->id, 'last_post_date_gmt');
1142
+ if (!empty($last_date_gmt)) {
1143
  $where .= ' AND post_date_gmt '.(('asc' == $this->scan->crawl_order)? '>=' : '<=').' "'.esc_sql($last_date_gmt).'"';
1144
+ }
1145
+
1146
  // Set arguments
1147
  $this->set_post_args();
1148
+
1149
  // Retrieve next post
1150
  $post = $wpdb->get_row('SELECT ID, post_content, post_date_gmt, post_type FROM '.$wpdb->posts.' WHERE '.$where.' AND post_type '.$this->post_args['post_types'].' AND post_status '.$this->post_args['post_status'].$this->post_args['time_scope'].$this->post_args['content_filters'].' ORDER BY '.$this->post_args['order_by'].' LIMIT 1');
1151
+
1152
  // Check if post is previously registered
1153
  if (!empty($post) && $this->scans->scan_object_exists($this->scan->id, $post->ID, 'posts')) {
1154
+
1155
  // Prepare identifiers
1156
  $ids = array($post->ID);
1157
+
1158
  // Check same value of last date
1159
  if ($post->post_date_gmt == $last_date_gmt) {
1160
+
1161
  // Check more identifiers with same date
1162
  $existing_ids = $this->scans->get_scan_objects_ids_by_date($this->scan->id, 'posts', $last_date_gmt);
1163
+ if (!empty($existing_ids) && is_array($existing_ids)) {
1164
  $ids = array_unique(array_merge($ids, $existing_ids));
1165
+ }
1166
  }
1167
+
1168
  // Add exceptions
1169
  $exceptions = empty($exceptions)? $ids : array_unique(array_merge($exceptions, $ids));
1170
+
1171
  // Next post with exceptions
1172
  $post = $this->content_posts_next($exceptions);
1173
  }
1174
+
1175
  // Done
1176
  return empty($post)? false : $post;
1177
  }
1182
  * Obtains and process contents from comments
1183
  */
1184
  private function content_comments() {
1185
+
1186
  // Recursion limit
1187
  static $recursion;
1188
  $recursion = isset($recursion)? 1 : $recursion + 1;
1190
  $this->restart();
1191
  return false;
1192
  }
1193
+
1194
  // Content max pack
1195
  $this->pack_index++;
1196
  if ($this->pack_index > wplnst_get_nsetting('max_pack')) {
1197
  $this->restart();
1198
  return false;
1199
  }
1200
+
1201
  // Check next comment
1202
  if (false !== ($comment = $this->content_comments_next())) {
1203
+
1204
  // Register object
1205
+ if (!$this->scans->register_scan_object($this->scan->id, $comment->comment_ID, 'comments', $comment->comment_date_gmt)) {
1206
  return $this->content_comments();
1207
+ }
1208
+
1209
  // Update last date gmt
1210
  $this->scans->update_scan_trace($this->scan->id, array('last_comment_date_gmt' => $comment->comment_date_gmt));
1211
+
1212
  // Update comments index
1213
  $this->scans->update_scan_trace($this->scan->id, array('comments_index' => $this->scans->get_scan_objects_count($this->scan->id, 'comments')));
1214
+
1215
  // Initialize
1216
  $links_added = array();
1217
  $images_added = array();
1218
  $authors_added = array();
1219
+
1220
  // Retrieve parent permalink
1221
  $parent_url = array('post_id' => $comment->comment_post_ID);
1222
+
1223
  // Process content
1224
  if (!empty($comment->comment_content)) {
1225
+
1226
  // Process links
1227
  if (in_array('links', $this->scan->link_types)) {
1228
  $links = $this->extract_links($comment->comment_content, $parent_url, $comment->comment_ID, 'comments', "", 'comment_content', $comment->comment_date_gmt);
1229
+ if (!empty($links)) {
1230
  $links_added = $this->save($links, $comment->comment_post_ID);
1231
+ }
1232
  }
1233
+
1234
  // Process images
1235
  if (in_array('images', $this->scan->link_types)) {
1236
  $images = $this->extract_images($comment->comment_content, $parent_url, $comment->comment_ID, 'comments', "", 'comment_content', $comment->comment_date_gmt);
1237
+ if (!empty($images)) {
1238
  $images_added = $this->save($images, $comment->comment_post_ID);
1239
+ }
1240
  }
1241
  }
1242
+
1243
  // Process author URL
1244
  if (!empty($comment->comment_author_url) && in_array('links', $this->scan->link_types)) {
1245
+
1246
  // Check URL
1247
  $urlinfo = $this->urlo->parse($comment->comment_author_url, $parent_url);
1248
  if ($this->filter_include_urls($urlinfo['url']) && $this->filter_exclude_urls($urlinfo['url'])) {
1249
+
1250
  // Check anchor
1251
  if ($this->filter_anchor_text($comment->comment_author)) {
1252
+
1253
  // Create link array
1254
  $link = array_merge($urlinfo, array(
1255
  'anchor' => $comment->comment_author,
1260
  'object_field' => 'comment_author_url',
1261
  'object_date_gmt' => $comment->comment_date_gmt,
1262
  ));
1263
+
1264
  // Author links
1265
  $authors_added = $this->save(array($link), $comment->comment_post_ID);
1266
  }
1267
  }
1268
  }
1269
+
1270
  // Update stats for summary
1271
  if (!empty($links_added) || !empty($images_added) || !empty($authors_added)) {
1272
+
1273
  // Update URLs phases
1274
  $this->scans->set_scan_summary_urls_phases($this->scan->id);
1275
+
1276
  // Update objects matched
1277
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'comments');
1278
+
1279
  // Totals of content for each URL status added
1280
  $added = array_unique(array_merge($links_added, $images_added, $authors_added));
1281
+ foreach ($added as $url_id) {
1282
  $this->scans->set_scan_url_status_total_content($url_id, $this->scan->id);
1283
+ }
1284
+
1285
  // Check inspect data
1286
+ if ($this->inspect()) {
1287
  return false;
1288
+ }
1289
  }
1290
+
1291
  // Empty
1292
  } elseif ($this->scans->get_scan_objects_count($this->scan->id, 'comments') >= $this->total_comments) {
1293
+
1294
  // Update populated status
1295
  $this->scans->update_scan_trace($this->scan->id, array('populated_comments' => true));
1296
+
1297
  // Check inspect data
1298
+ if ($this->inspect()) {
1299
  return false;
1300
+ }
1301
+
1302
  // Check data to inspect
1303
  } elseif ($this->inspect()) {
1304
+
1305
  // Working
1306
  return false;
1307
  }
1308
+
1309
  // End or next comment
1310
  return $this->scans->get_scan_trace($this->scan->id, 'populated_comments')? true : $this->content_comments();
1311
  }
1316
  * Retrieve next comment
1317
  */
1318
  private function content_comments_next($exceptions = array()) {
1319
+
1320
  // Globals
1321
  global $wpdb;
1322
+
1323
  // Initialize
1324
  $where = '1 = 1';
1325
+
1326
  // Check exceptions
1327
+ if (!empty($exceptions)) {
1328
  $where .= ' AND comment_ID NOT IN ('.implode(',', array_map('intval', $exceptions)).')';
1329
+ }
1330
+
1331
  // Check last date condition
1332
  $last_date_gmt = $this->scans->get_scan_trace($this->scan->id, 'last_comment_date_gmt');
1333
+ if (!empty($last_date_gmt)) {
1334
  $where .= ' AND comment_date_gmt '.(('asc' == $this->scan->crawl_order)? '>=' : '<=').' "'.esc_sql($last_date_gmt).'"';
1335
+ }
1336
+
1337
  // Set arguments
1338
  $this->set_comment_args();
1339
+
1340
  // Retrieve next comment
1341
  $comment = $wpdb->get_row('SELECT comment_ID, comment_post_ID, comment_content, comment_author, comment_author_url, comment_date_gmt FROM '.$wpdb->comments.' WHERE '.$where.' '.$this->comment_args['comment_status'].$this->comment_args['time_scope'].$this->comment_args['content_filters'].' ORDER BY '.$this->comment_args['order_by'].' LIMIT 1');
1342
+
1343
  // Check if comment id previously registered
1344
  if (!empty($comment) && $this->scans->scan_object_exists($this->scan->id, $comment->comment_ID, 'comments')) {
1345
+
1346
  // Prepare identifiers
1347
  $ids = array($comment->comment_ID);
1348
+
1349
  // Check same value of last date
1350
  if ($comment->comment_date_gmt == $last_date_gmt) {
1351
+
1352
  // Check more identifiers with same date
1353
  $existing_ids = $this->scans->get_scan_objects_ids_by_date($this->scan->id, 'comments', $last_date_gmt);
1354
+ if (!empty($existing_ids) && is_array($existing_ids)) {
1355
  $ids = array_unique(array_merge($ids, $existing_ids));
1356
+ }
1357
  }
1358
+
1359
  // Add exceptions
1360
  $exceptions = empty($exceptions)? $ids : array_unique(array_merge($exceptions, $ids));
1361
+
1362
  // Next comment with exceptions
1363
  $comment = $this->content_comments_next($exceptions);
1364
  }
1365
+
1366
  // Done
1367
  return empty($comment)? false : $comment;
1368
  }
1373
  * Obtains and process links from the blogroll
1374
  */
1375
  private function content_blogroll() {
1376
+
1377
  // Recursion limit
1378
  static $recursion;
1379
  $recursion = isset($recursion)? 1 : $recursion + 1;
1381
  $this->restart();
1382
  return false;
1383
  }
1384
+
1385
  // Content max pack
1386
  $this->pack_index++;
1387
  if ($this->pack_index > wplnst_get_nsetting('max_pack')) {
1388
  $this->restart();
1389
  return false;
1390
  }
1391
+
1392
  // Check next blogroll link
1393
  if (false !== ($blogroll_link = $this->content_blogroll_next())) {
1394
+
1395
  // Register object
1396
+ if (!$this->scans->register_scan_object($this->scan->id, $blogroll_link->link_id, 'blogroll')) {
1397
  return $this->content_blogroll();
1398
+ }
1399
+
1400
  // Update last blogroll id
1401
  $this->scans->update_scan_trace($this->scan->id, array('last_blogroll_id' => $blogroll_link->link_id));
1402
+
1403
  // Update blogroll index
1404
  $this->scans->update_scan_trace($this->scan->id, array('blogroll_index' => $this->scans->get_scan_objects_count($this->scan->id, 'blogroll')));
1405
+
1406
  // Process link URL
1407
  if (!empty($blogroll_link->link_url)) {
1408
+
1409
  // Check URL
1410
  $urlinfo = $this->urlo->parse($blogroll_link->link_url);
1411
  if ($this->filter_include_urls($urlinfo['url']) && $this->filter_exclude_urls($urlinfo['url'])) {
1412
+
1413
+ // Check anchor
1414
  if ($this->filter_anchor_text($blogroll_link->link_name)) {
1415
+
1416
  // Create link array
1417
  $link = array_merge($urlinfo, array(
1418
  'anchor' => $blogroll_link->link_name,
1423
  'object_field' => 'link_url',
1424
  'object_date_gmt' => '0000-00-00 00:00:00',
1425
  ));
1426
+
1427
  // Add blogroll link
1428
  $blogroll_added = $this->save(array($link));
1429
+
1430
  // Update URLs phases
1431
  $this->scans->set_scan_summary_urls_phases($this->scan->id);
1432
+
1433
  // Update objects matched
1434
  $this->scans->set_scan_summary_objects_match($this->scan->id, 'blogroll');
1435
+
1436
  // Totals of content for each URL status added
1437
+ foreach ($blogroll_added as $url_id) {
1438
  $this->scans->set_scan_url_status_total_content($url_id, $this->scan->id);
1439
+ }
1440
+
1441
  // Check inspect data
1442
+ if ($this->inspect()) {
1443
  return false;
1444
+ }
1445
  }
1446
  }
1447
  }
1448
+
1449
  // Empty
1450
  } elseif ($this->scans->get_scan_objects_count($this->scan->id, 'blogroll') >= $this->total_blogroll) {
1451
+
1452
  // Update populated status
1453
  $this->scans->update_scan_trace($this->scan->id, array('populated_blogroll' => true));
1454
+
1455
  // Check inspect data
1456
+ if ($this->inspect()) {
1457
  return false;
1458
+ }
1459
+
1460
  // Check data to inspect
1461
  } elseif ($this->inspect()) {
1462
+
1463
  // Working
1464
  return false;
1465
  }
1466
+
1467
  // End or next blogroll link
1468
  return $this->scans->get_scan_trace($this->scan->id, 'populated_blogroll')? true : $this->content_blogroll();
1469
  }
1474
  * Retrieve next blogroll link
1475
  */
1476
  private function content_blogroll_next($exceptions = array()) {
1477
+
1478
  // Globals
1479
  global $wpdb;
1480
+
1481
  // Initialize
1482
  $where = '1 = 1';
1483
+
1484
  // Check exceptions
1485
+ if (!empty($exceptions)) {
1486
  $where .= ' AND link_id NOT IN ('.implode(',', array_map('intval', $exceptions)).')';
1487
+ }
1488
+
1489
  // Check last identifier condition
1490
  $last_id = (int) $this->scans->get_scan_trace($this->scan->id, 'last_blogroll_id');
1491
+ if (!empty($last_id)) {
1492
  $where .= ' AND link_id '.(('asc' == $this->scan->crawl_order)? '>' : '<').' '.$last_id;
1493
+ }
1494
 
1495
  // Set arguments
1496
  $this->set_blogroll_args();
1497
+
1498
  // Query next blogroll link
1499
  $bookmark = $wpdb->get_row('SELECT link_id, link_url, link_name FROM '.$wpdb->links.' WHERE '.$where.' ORDER BY '.$this->blogroll_args['order_by'].' LIMIT 1');
1500
+
1501
  // Check if bookmark is previously registered
1502
  if (!empty($bookmark) && $this->scans->scan_object_exists($this->scan->id, $bookmark->link_id, 'blogroll')) {
1503
  $exceptions[] = $bookmark->link_id;
1504
  $bookmark = $this->content_blogroll_next($exceptions);
1505
  }
1506
+
1507
  // Done
1508
  return empty($bookmark)? false : $bookmark;
1509
  }
1514
  * Extract links from content
1515
  */
1516
  private function extract_links($content, $parent_url, $object_id, $object_type, $object_post_type, $object_field, $object_date_gmt) {
1517
+
1518
  // Initialize
1519
  $links = array();
1520
+
1521
  // Check links
1522
  if (preg_match_all('/(<a[^>]+href=["|\'](.+)["|\'][^>]*>)(.*)<\/a>/isUu', $content, $matches, PREG_SET_ORDER) > 0) {
1523
+
1524
  // Enum matched links tags
1525
  foreach ($matches as $match) {
1526
+
1527
  // Skip page anchor
1528
+ if ('#' == mb_substr($match[2], 0, 1)) {
1529
  continue;
1530
+ }
1531
+
1532
  // Check anchor
1533
  $anchor = $match[3];
1534
+ if (!$this->filter_anchor_text($anchor)) {
1535
  continue;
1536
+ }
1537
+
1538
  // Check URL
1539
  $urlinfo = $this->urlo->parse($match[2], $parent_url);
1540
+ if (!$this->filter_include_urls($urlinfo['url']) || !$this->filter_exclude_urls($urlinfo['url'])) {
1541
  continue;
1542
+ }
1543
+
1544
  // Check attributes
1545
  $attributes = $this->urlo->extract_attributes($match[1]);
1546
+ if (!$this->filter_html_attributes('a', $attributes)) {
1547
  continue;
1548
+ }
1549
+
1550
  // Check nofollow
1551
  $nofollow = false;
1552
  if (!empty($attributes['rel'])) {
1553
  $values = explode(' ', strtolower(str_replace("\n", ' ', str_replace("\r", ' ', $attributes['rel']))));
1554
+ if (in_array('nofollow', $values)) {
1555
  $nofollow = true;
1556
+ }
1557
  }
1558
+
1559
  // Add item
1560
  $links[] = array_merge($urlinfo, array(
1561
  'chunk' => $match[0],
1571
  ));
1572
  }
1573
  }
1574
+
1575
  // Done
1576
  return $links;
1577
  }
1582
  * Extract images from content
1583
  */
1584
  private function extract_images($content, $parent_url, $object_id, $object_type, $object_post_type, $object_field, $object_date_gmt) {
1585
+
1586
  // Initialize
1587
  $images = array();
1588
+
1589
  // Check links
1590
  if (preg_match_all('/<img[^>]+src=["|\'](.+)["|\'][^>]*>/isUu', $content, $matches, PREG_SET_ORDER) > 0) {
1591
+
1592
  // Enum matched links tags
1593
  foreach ($matches as $match) {
1594
+
1595
  // Skip page anchor
1596
+ if ('#' == mb_substr($match[1], 0, 1)) {
1597
  continue;
1598
+ }
1599
+
1600
  // Check URL
1601
  $urlinfo = $this->urlo->parse($match[1], $parent_url);
1602
+ if (!$this->filter_include_urls($urlinfo['url']) || !$this->filter_exclude_urls($urlinfo['url'])) {
1603
  continue;
1604
+ }
1605
+
1606
  // Check attributes
1607
  $attributes = $this->urlo->extract_attributes($match[0]);
1608
+ if (!$this->filter_html_attributes('img', $attributes)) {
1609
  continue;
1610
+ }
1611
+
1612
  // Add item
1613
  $images[] = array_merge($urlinfo, array(
1614
  'chunk' => $match[0],
1622
  ));
1623
  }
1624
  }
1625
+
1626
  // Done
1627
  return $images;
1628
  }
1638
  * Check if passes anchor text filters
1639
  */
1640
  private function filter_anchor_text($anchor) {
1641
+
1642
  // Check filters
1643
+ if (empty($this->scan->anchor_filters)) {
1644
  return true;
1645
+ }
1646
+
1647
  // Initialize
1648
  $passed = array();
1649
+
1650
  // Version without tags
1651
  $anchor_text = strip_tags($anchor);
1652
+
1653
  // Enum filters
1654
  foreach ($this->scan->anchor_filters as $filter) {
1655
+
1656
  // Check filter
1657
+ if (empty($filter['type']) || !isset($filter['value'])) {
1658
  continue;
1659
+ }
1660
+
1661
  // Check if contains a value
1662
  if ('contains' == $filter['type']) {
1663
+
1664
  // Continue if passed
1665
+ if (isset($passed['contains']) && true === $passed['contains']) {
1666
  continue;
1667
+ }
1668
+
1669
  // Check tag in filter
1670
  $is_filter_tag = (false !== strpos($filter['value'], '<') || false !== strpos($filter['value'], '>'));
1671
+
1672
  // Test
1673
  $passed['contains'] = (false !== stripos($anchor_text, $filter['value'])) || ($is_filter_tag && false !== stripos($anchor, $filter['value']));
1674
+
1675
  // Check if not contain a value
1676
  } elseif ('not-contains' == $filter['type']) {
1677
+
1678
  // Continue if passed
1679
+ if (isset($passed['contains']) && false === $passed['contains']) {
1680
  continue;
1681
+ }
1682
+
1683
  // Check tag in filter
1684
  $is_filter_tag = (false !== strpos($filter['value'], '<') || false !== strpos($filter['value'], '>'));
1685
+
1686
  // Test
1687
  $passed['not-contains'] = (false === stripos($anchor_text, $filter['value'])) || ($is_filter_tag && false === stripos($anchor, $filter['value']));
1688
+
1689
  // Check if equal to a value
1690
  } elseif ('equal-to' == $filter['type']) {
1691
+
1692
  // Continue if passed
1693
+ if (isset($passed['equal-to']) && true === $passed['equal-to']) {
1694
  continue;
1695
+ }
1696
+
1697
  // Test
1698
  $passed['equal-to'] = ($anchor == $filter['value']);
1699
+
1700
  // Check if not equal to a value
1701
  } elseif ('not-equal-to' == $filter['type']) {
1702
+
1703
  // Continue if passed
1704
+ if (isset($passed['not-equal-to']) && false === $passed['not-equal-to']) {
1705
  continue;
1706
+ }
1707
+
1708
  // Test
1709
  $passed['not-equal-to'] = ($anchor != $filter['value']);
1710
+
1711
  // Check if begins with value
1712
  } elseif ('begins-with' == $filter['type']) {
1713
+
1714
  // Continue if passed
1715
+ if (isset($passed['begins-with']) && true === $passed['begins-with']) {
1716
  continue;
1717
+ }
1718
+
1719
  // Test
1720
  $passed['begins-with'] = (0 === stripos($anchor, $filter['value']));
1721
+
1722
  // Check if ends with value
1723
  } elseif ('ends-by' == $filter['type']) {
1724
+
1725
  // Continue if passed
1726
+ if (isset($passed['ends-by']) && true === $passed['ends-by']) {
1727
  continue;
1728
+ }
1729
+
1730
  // Test
1731
  $passed['ends-by'] = (($temp = strlen($anchor) - strlen($filter['value'])) >= 0 && stripos($anchor, $filter['value'], $temp) !== false);
1732
+
1733
  // Check if is empty
1734
  } elseif ('empty' == $filter['type']) {
1735
+
1736
  // Continue if passed
1737
+ if (isset($passed['empty'])) {
1738
  continue;
1739
+ }
1740
+
1741
  // Test
1742
  $passed['empty'] = ($anchor === '');
1743
  }
1744
  }
1745
+
1746
  // Check filters
1747
  $checks = array('contains', 'not-contains', 'equal-to', 'not-equal', 'begins-with', 'ends-by', 'empty');
1748
  foreach ($checks as $check) {
1749
+ if (isset($passed[$check]) && false === $passed[$check]) {
1750
  return false;
1751
+ }
1752
  }
1753
+
1754
  // Done
1755
  return true;
1756
  }
1761
  * Filter for URL including
1762
  */
1763
  private function filter_include_urls($url) {
1764
+
1765
  // Check filters
1766
+ if (empty($this->scan->include_urls)) {
1767
  return true;
1768
+ }
1769
+
1770
  // Initialize
1771
  $passed = array();
1772
+
1773
  // Enum filters
1774
  foreach ($this->scan->include_urls as $filter) {
1775
+
1776
  // Check filter
1777
+ if (empty($filter['type']) || !isset($filter['value'])) {
1778
  continue;
1779
+ }
1780
+
1781
  // Check if match all value
1782
  if ('full-url' == $filter['type']) {
1783
+
1784
  // Continue if passed
1785
+ if (isset($passed['full-url']) && true === $passed['full-url']) {
1786
  continue;
1787
+ }
1788
+
1789
  // Test
1790
  $passed['full-url'] = ($url == $filter['value']);
1791
+
1792
  // Check if match a value
1793
  } elseif ('matched-string' == $filter['type']) {
1794
+
1795
  // Continue if passed
1796
+ if (isset($passed['matched-string']) && true === $passed['matched-string']) {
1797
  continue;
1798
+ }
1799
+
1800
  // Test
1801
  $passed['matched-string'] = (false !== stripos($url, $filter['value']));
1802
+
1803
  // Check if is prefixed
1804
  } elseif ('url-prefix' == $filter['type']) {
1805
+
1806
  // Continue if passed
1807
+ if (isset($passed['url-prefix']) && true === $passed['url-prefix']) {
1808
  continue;
1809
+ }
1810
+
1811
  // Test
1812
  $passed['url-prefix'] = (0 === stripos($url, $filter['value']));
1813
+
1814
  // Check if ends with value
1815
  } elseif ('url-suffix' == $filter['type']) {
1816
+
1817
  // Continue if passed
1818
+ if (isset($passed['url-suffix']) && true === $passed['url-suffix']) {
1819
  continue;
1820
+ }
1821
+
1822
  // Test
1823
  $passed['url-suffix'] = (($temp = strlen($url) - strlen($filter['value'])) >= 0 && stripos($url, $filter['value'], $temp) !== false);
1824
  }
1825
  }
1826
+
1827
  // Check filters
1828
  $checks = array('full-url', 'matched-string', 'url-prefix', 'url-suffix');
1829
  foreach ($checks as $check) {
1830
+ if (isset($passed[$check]) && false === $passed[$check]) {
1831
  return false;
1832
+ }
1833
  }
1834
+
1835
  // Done
1836
  return true;
1837
  }
1842
  * Filter for URL excluding
1843
  */
1844
  private function filter_exclude_urls($url) {
1845
+
1846
  // Check filters
1847
+ if (empty($this->scan->exclude_urls)) {
1848
  return true;
1849
+ }
1850
+
1851
  // Initialize
1852
  $passed = array();
1853
+
1854
  // Enum filters
1855
  foreach ($this->scan->exclude_urls as $filter) {
1856
+
1857
  // Check filter
1858
+ if (empty($filter['type']) || !isset($filter['value'])) {
1859
  continue;
1860
+ }
1861
+
1862
  // Check if match all value
1863
  if ('full-url' == $filter['type']) {
1864
+
1865
  // Continue if passed
1866
+ if (isset($passed['full-url']) && false === $passed['full-url']) {
1867
  continue;
1868
+ }
1869
+
1870
  // Test
1871
  $passed['full-url'] = ($url != $filter['value']);
1872
+
1873
  // Check if match a value
1874
  } elseif ('matched-string' == $filter['type']) {
1875
+
1876
  // Continue if passed
1877
+ if (isset($passed['matched-string']) && false === $passed['matched-string']) {
1878
  continue;
1879
+ }
1880
+
1881
  // Test
1882
  $passed['matched-string'] = (false === stripos($url, $filter['value']));
1883
+
1884
  // Check if is prefixed
1885
  } elseif ('url-prefix' == $filter['type']) {
1886
+
1887
  // Continue if passed
1888
+ if (isset($passed['url-prefix']) && false === $passed['url-prefix']) {
1889
  continue;
1890
+ }
1891
+
1892
  // Test
1893
  $passed['url-prefix'] = (0 !== stripos($url, $filter['value']));
1894
+
1895
  // Check if ends with value
1896
  } elseif ('url-suffix' == $filter['type']) {
1897
+
1898
  // Continue if passed
1899
+ if (isset($passed['url-suffix']) && false === $passed['url-suffix']) {
1900
  continue;
1901
+ }
1902
+
1903
  // Test
1904
  $passed['url-suffix'] = (($temp = strlen($url) - strlen($filter['value'])) >= 0 && stripos($url, $filter['value'], $temp) === false);
1905
  }
1906
  }
1907
+
1908
  // Check filters
1909
  $checks = array('full-url', 'matched-string', 'url-prefix', 'url-suffix');
1910
  foreach ($checks as $check) {
1911
+ if (isset($passed[$check]) && false === $passed[$check]) {
1912
  return false;
1913
+ }
1914
  }
1915
+
1916
  // Done
1917
  return true;
1918
  }
1923
  * Filter based on attributes
1924
  */
1925
  private function filter_html_attributes($element, $attributes) {
1926
+
1927
  // Check filters
1928
+ if (empty($this->scan->html_attributes)) {
1929
  return true;
1930
+ }
1931
+
1932
  // Initialize
1933
  $passed = array();
1934
+
1935
  // Isolate attributes
1936
  $att_names = array_keys($attributes);
1937
+
1938
  // Enum filters
1939
  foreach ($this->scan->html_attributes as $filter) {
1940
+
1941
  // Check filter
1942
+ if (empty($filter['element']) || $element != $filter['element'] || !isset($filter['att']) || empty($filter['having'])) {
1943
  continue;
1944
+ }
1945
+
1946
  // Check if not have an attribute
1947
  if ('not-have' == $filter['having']) {
1948
+
1949
  // Continue if not passed
1950
+ if (isset($passed['not-have']) && false === $passed['not-have']) {
1951
  continue;
1952
+ }
1953
+
1954
  // Test
1955
  $passed['not-have'] = !in_array($filter['att'], $att_names);
1956
+
1957
  // Contains
1958
  } elseif ('contains' == $filter['op']) {
1959
+
1960
  // Continue if passed
1961
+ if (isset($passed['contains']) && true === $passed['contains']) {
1962
  continue;
1963
+ }
1964
+
1965
  // Need a filter value
1966
  if (!isset($filter['value']) || '' === ''.trim($filter['value'])) {
1967
  $passed['contains'] = false;
1968
  continue;
1969
  }
1970
+
1971
  // Check att name compatibility
1972
  if (!in_array($filter['att'], $att_names)) {
1973
  $passed['contains'] = false;
1974
  continue;
1975
  }
1976
+
1977
  // Final test
1978
  $passed['contains'] = in_array(strtolower($filter['value']), $att_values)? $filter['value'] : false;
1979
+
1980
  // Not contains
1981
  } elseif ('not-contains' == $filter['op']) {
1982
+
1983
  // Continue if passed
1984
+ if (isset($passed['not-contains']) && true === $passed['not-contains']) {
1985
  continue;
1986
+ }
1987
+
1988
  // Need a filter value
1989
  if (!isset($filter['value']) || '' === ''.trim($filter['value'])) {
1990
  $passed['not-contains'] = false;
1991
  continue;
1992
  }
1993
+
1994
  // Check att name compatibility
1995
  if (!in_array($filter['att'], $att_names)) {
1996
  $passed['not-contains'] = false;
1997
  continue;
1998
  }
1999
+
2000
  // Final test
2001
  $passed['not-contains'] = !in_array(strtolower($filter['value']), $att_values)? $filter['value'] : false;
2002
+
2003
  // Equal
2004
  } elseif ('equal' == $filter['op']) {
2005
+
2006
  // Continue if passed
2007
+ if (isset($passed['equal']) && true === $passed['equal']) {
2008
  continue;
2009
+ }
2010
+
2011
  // Test
2012
  $passed['equal'] = in_array($filter['att'], $att_names)? ($attributes[$filter['att']] == (isset($filter['value'])? $filter['value'] : '')) : false;
2013
+
2014
  // Not equal
2015
  } elseif ('not-equal' == $filter['op']) {
2016
+
2017
  // Continue if passed
2018
+ if (isset($passed['not-equal']) && false === $passed['not-equal']) {
2019
  continue;
2020
+ }
2021
+
2022
  // Test
2023
  $passed['not-equal'] = in_array($filter['att'], $att_names)? ($attributes[$filter['att']] != (isset($filter['value'])? $filter['value'] : '')) : false;
2024
+
2025
  // Not empty value
2026
  } elseif ('not-empty' == $filter['op']) {
2027
+
2028
  // Continue if passed
2029
+ if (isset($passed['not-empty']) && false === $passed['not-empty']) {
2030
  continue;
2031
+ }
2032
+
2033
  // Test
2034
  $passed['not-empty'] = in_array($filter['att'], $att_names)? ($attributes[$filter['att']] !== '') : false;
2035
+
2036
  // Empty value
2037
  } elseif ('empty' == $filter['op']) {
2038
+
2039
  // Continue if passed
2040
+ if (isset($passed['empty']) && false === $passed['empty']) {
2041
  continue;
2042
+ }
2043
+
2044
  // Test
2045
  $passed['empty'] = in_array($filter['att'], $att_names)? ($attributes[$filter['att']] === '') : false;
2046
  }
2047
  }
2048
+
2049
  // Check filters
2050
  $checks = array('not-have', 'contains', 'not-contains', 'equal', 'not-equal', 'not-empty', 'empty');
2051
  foreach ($checks as $check) {
2052
+ if (isset($passed[$check]) && false === $passed[$check]) {
2053
  return false;
2054
+ }
2055
  }
2056
+
2057
  // Done
2058
  return true;
2059
  }
2064
  * Extract filter content for queries
2065
  */
2066
  private function filter_for_queries() {
2067
+
2068
+
2069
  /* Initialization */
2070
+
2071
  // Check cache
2072
  static $matches;
2073
+ if (isset($matches)) {
2074
  return $matches;
2075
+ }
2076
  $matches = array();
2077
+
2078
  // Check configuration
2079
+ if (!$this->scan->filtered_query) {
2080
  return $matches;
2081
+ }
2082
+
2083
+
2084
  /* Anchor filters */
2085
+
2086
  // Check anchor filters
2087
  if (!empty($this->scan->anchor_filters)) {
2088
+
2089
  // Enum anchor filters
2090
  foreach ($this->scan->anchor_filters as $filter) {
2091
+
2092
  // Check filter
2093
+ if (empty($filter['type']) || !isset($filter['value']) || '' === ''.trim($filter['value'])) {
2094
  continue;
2095
+ }
2096
+
2097
  // Match filters
2098
  if (in_array($filter['type'], array('contains', 'equal-to', 'begins-with', 'ends-by'))) {
2099
+
2100
  // Need this string
2101
  $matches[] = $filter['value'];
2102
  }
2103
  }
2104
  }
2105
+
2106
+
2107
  /* Include URLs */
2108
+
2109
  // Check include filters
2110
  if (!empty($this->scan->include_urls)) {
2111
+
2112
  // Enum include filters
2113
  foreach ($this->scan->include_urls as $filter) {
2114
+
2115
  // Check filter
2116
+ if (empty($filter['type']) || !isset($filter['value']) || '' === ''.trim($filter['value'])) {
2117
  continue;
2118
+ }
2119
+
2120
  // Match filters
2121
  if (in_array($filter['type'], array('full-url', 'matched-string', 'url-prefix', 'url-suffix'))) {
2122
+
2123
  // Need this string
2124
  $matches[] = $filter['value'];
2125
  }
2126
  }
2127
  }
2128
+
2129
+
2130
  /* HTML attributes */
2131
+
2132
  // Check attributes filters
2133
  if (!empty($this->scan->html_attributes)) {
2134
+
2135
  // Enum filters
2136
  foreach ($this->scan->html_attributes as $filter) {
2137
+
2138
  // Check filter value
2139
+ if (!isset($filter['value']) || '' === ''.trim($filter['value'])) {
2140
  continue;
2141
+ }
2142
+
2143
  // Check having and attribute part
2144
+ if (empty($filter['having']) || 'have' != $filter['having'] || empty($filter['att']) || '' == 'att'.trim($filter['att'])) {
2145
  continue;
2146
+ }
2147
+
2148
  // Check operation
2149
+ if (empty($filter['op']) || !in_array($filter['op'], array('contains', 'equal'))) {
2150
  continue;
2151
+ }
2152
+
2153
  // Add string
2154
  $matches[] = $filter['value'];
2155
  }
2156
  }
2157
+
2158
+
2159
  // Done
2160
  return $matches;
2161
  }
2171
  * Save links
2172
  */
2173
  private function save($links, $parent_post_id = 0) {
2174
+
2175
  // Initialize
2176
  $statuses = array();
2177
+
2178
  // Enum links
2179
  foreach ($links as $link) {
2180
+
2181
  // Avoid empty URLs
2182
+ if ('' === ''.trim($link['url'])) {
2183
  continue;
2184
+ }
2185
+
2186
  // Malformed links tracking
2187
  if ($link['malformed']) {
2188
+ if (!$this->scan->malformed) {
2189
  continue;
2190
+ }
2191
  }
2192
+
2193
  // Search by main URL
2194
  if (false !== ($row = $this->scans->get_scan_url(array('url' => $link['url'], 'no_cache' => true)))) {
2195
  $url_id = $row->url_id;
2196
+
2197
  // Register scan URL
2198
  } elseif (false === ($url_id = $this->scans->add_scan_url($link, $this->scan->id))) {
2199
  continue;
2200
  }
2201
+
2202
  // Check destination type
2203
+ if (isset($link['scope']) && in_array($this->scan->destination_type, array('internal', 'external')) && $link['scope'] != $this->scan->destination_type) {
2204
  continue;
2205
+ }
2206
+
2207
  // Save URL location
2208
  $this->scans->add_scan_url_location($url_id, $this->scan->id, $link);
2209
+
2210
  // Check our tiny cache
2211
+ if (in_array($url_id, $statuses)) {
2212
  continue;
2213
+ }
2214
+
2215
  // Check if exists a previous status identifier
2216
  if (false !== $this->scans->get_scan_url_status(array('url_id' => $url_id, 'scan_id' => $this->scan->id))) {
2217
  $statuses[] = $url_id;
2218
  continue;
2219
  }
2220
+
2221
  // Check phase
2222
  $phase = $this->urlo->is_crawleable($link)? 'wait' : 'end';
2223
+
2224
  // Create URL status
2225
  $this->scans->add_scan_url_status($url_id, $this->scan->id, $phase);
2226
+
2227
  // Status on
2228
  $statuses[] = $url_id;
2229
  }
2230
+
2231
  // Done
2232
  return $statuses;
2233
  }
2243
  * Cast relative URLs to absolute
2244
  */
2245
  public function parent_permalink($parent) {
2246
+
2247
  // Check array
2248
+ if (!is_array($parent) || !isset($parent['post_id'])) {
2249
  return false;
2250
+ }
2251
+
2252
  // Check identifier
2253
  $post_id = (int) $parent['post_id'];
2254
+ if (empty($post_id)) {
2255
  return false;
2256
+ }
2257
+
2258
  // Return permalink
2259
  return $this->get_permalink($post_id);
2260
  }
2267
  * so we use the short permalink form to catch the redirection.
2268
  */
2269
  private function get_permalink($post_id) {
2270
+
2271
  // Permalinks cache
2272
  static $permalinks;
2273
+ if (!isset($permalinks)) {
2274
  $permalinks = array();
2275
+ }
2276
+
2277
  // Check cache
2278
+ if (isset($permalinks[$post_id])) {
2279
  return $permalinks[$post_id];
2280
+ }
2281
+
2282
  // Initialize
2283
  $permalinks[$post_id] = false;
2284
+
2285
  // Load cURL wrapper library
2286
  wplnst_require('core', 'curl');
2287
+
2288
  // cURL request
2289
  $response = WPLNST_Core_CURL::request(array(
2290
  'CURLOPT_URL' => $this->urlo->home_url.'/?p='.$post_id,
2298
  'CURLOPT_TIMEOUT' => $this->request_timeout,
2299
  'CURLOPT_USERAGENT' => wplnst_get_tsetting('user_agent'),
2300
  ));
2301
+
2302
  // Check response
2303
+ if ($response['error']) {
2304
  return false;
2305
+ }
2306
 
2307
  // Check response
2308
  $data = trim($response['data']);
2309
+ if (empty($data)) {
2310
  return false;
2311
+ }
2312
+
2313
  // Enum response links
2314
  $data = explode("\n", $data);
2315
  foreach ($data as $line) {
2316
+
2317
  // Clear line
2318
  $line = trim(preg_replace('/\s+/', ' ', $line));
2319
+
2320
  // Check redirection in status code
2321
  if (!isset($status_code) && 0 === stripos($line, 'HTTP/')) {
2322
  $line = explode(' ', $line);
2323
  if (count($line) > 1) {
2324
  $status_code = trim($line[1]);
2325
+ if ('30' != mb_substr($status_code, 0, 2)) {
2326
  return false;
2327
+ }
2328
  }
2329
+
2330
  // Check Location
2331
  } elseif (isset($status_code) && 0 === stripos($line, 'location:')) {
2332
  $location = trim(mb_substr($line, 9));
2333
  $parts = @parse_url($location);
2334
+ if (!empty($parts['scheme']) && !empty($parts['host'])) {
2335
  $permalinks[$post_id] = $location;
2336
+ }
2337
  }
2338
  }
2339
+
2340
  // Done
2341
  return $permalinks[$post_id];
2342
  }
core/curl.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core CURL class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_CURL {
10
 
@@ -14,14 +14,14 @@ class WPLNST_Core_CURL {
14
  * Spawn async request
15
  */
16
  public static function spawn($setopts = array()) {
17
- self::request(array_merge(array(
18
  'CURLOPT_HEADER' => false,
19
  'CURLOPT_NOBODY' => true,
20
  'CURLOPT_FOLLOWLOCATION' => false,
21
  'CURLOPT_RETURNTRANSFER' => false,
22
  'CURLOPT_FRESH_CONNECT' => true,
23
- 'CURLOPT_CONNECTTIMEOUT' => 1,
24
- 'CURLOPT_TIMEOUT' => 1,
25
  ), $setopts));
26
  }
27
 
@@ -49,7 +49,7 @@ class WPLNST_Core_CURL {
49
  * Basic cURL wrapper
50
  */
51
  public static function request($setopts = array(), $getinfo = array()) {
52
-
53
  // Default
54
  $response = array(
55
  'data' => '',
@@ -60,64 +60,69 @@ class WPLNST_Core_CURL {
60
  'time' => 0,
61
  'timestamp' => 0,
62
  );
63
-
64
  // Check cURL support
65
  if (function_exists('wplnst_is_curl_enabled') && !wplnst_is_curl_enabled()) {
66
  $response['reason'] = 'curl_disabled';
67
  return $response;
68
  }
69
-
70
  // cURL session
71
  if (false === ($ch = @curl_init())) {
72
  $response['reason'] = 'curl_init';
73
  return $response;
74
  }
75
-
76
  // IP resolve options
77
- if (!isset($setopts['CURLOPT_IPRESOLVE']) && defined('CURL_IPRESOLVE_V4'))
78
  $setopts['CURLOPT_IPRESOLVE'] = CURL_IPRESOLVE_V4;
79
-
 
80
  // HTTPS checks
81
  if (!empty($setopts['CURLOPT_URL']) && 0 === strpos($setopts['CURLOPT_URL'], 'https')) {
82
- if (!isset($setopts['CURLOPT_SSL_VERIFYHOST']))
83
  $setopts['CURLOPT_SSL_VERIFYHOST'] = false;
84
- if (!isset($setopts['CURLOPT_SSL_VERIFYPEER']))
 
85
  $setopts['CURLOPT_SSL_VERIFYPEER'] = false;
 
86
  }
87
-
88
  // Apply options
89
  foreach ($setopts as $name => $value) {
90
- if (defined($name))
91
  @curl_setopt($ch, constant($name), $value);
 
92
  }
93
-
94
  // Now
95
  $response['timestamp'] = time();
96
-
97
  // Timer
98
  $time_start = microtime(true);
99
-
100
  // Retrieve response
101
  $response['data'] = @curl_exec($ch);
102
-
103
  // Time amount
104
  $response['time'] = microtime(true) - $time_start;
105
-
106
  // Copy error number
107
  $response['errno'] = (int) @curl_errno($ch);
108
-
109
  // Check info
110
  foreach ($getinfo as $info) {
111
- if (defined($info))
112
  $response['info'][$info] = @curl_getinfo($ch, constant($info));
 
113
  }
114
-
115
  // Close connection
116
  @curl_close($ch);
117
-
118
  // Check error
119
  $response['error'] = ($response['errno'] > 0);
120
-
121
  // Done
122
  return $response;
123
  }
1
  <?php
2
 
3
  /**
4
+ * CURL class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_CURL {
10
 
14
  * Spawn async request
15
  */
16
  public static function spawn($setopts = array()) {
17
+ return self::request(array_merge(array(
18
  'CURLOPT_HEADER' => false,
19
  'CURLOPT_NOBODY' => true,
20
  'CURLOPT_FOLLOWLOCATION' => false,
21
  'CURLOPT_RETURNTRANSFER' => false,
22
  'CURLOPT_FRESH_CONNECT' => true,
23
+ 'CURLOPT_CONNECTTIMEOUT' => 5,
24
+ 'CURLOPT_TIMEOUT' => 5,
25
  ), $setopts));
26
  }
27
 
49
  * Basic cURL wrapper
50
  */
51
  public static function request($setopts = array(), $getinfo = array()) {
52
+
53
  // Default
54
  $response = array(
55
  'data' => '',
60
  'time' => 0,
61
  'timestamp' => 0,
62
  );
63
+
64
  // Check cURL support
65
  if (function_exists('wplnst_is_curl_enabled') && !wplnst_is_curl_enabled()) {
66
  $response['reason'] = 'curl_disabled';
67
  return $response;
68
  }
69
+
70
  // cURL session
71
  if (false === ($ch = @curl_init())) {
72
  $response['reason'] = 'curl_init';
73
  return $response;
74
  }
75
+
76
  // IP resolve options
77
+ if (!isset($setopts['CURLOPT_IPRESOLVE']) && defined('CURL_IPRESOLVE_V4')) {
78
  $setopts['CURLOPT_IPRESOLVE'] = CURL_IPRESOLVE_V4;
79
+ }
80
+
81
  // HTTPS checks
82
  if (!empty($setopts['CURLOPT_URL']) && 0 === strpos($setopts['CURLOPT_URL'], 'https')) {
83
+ if (!isset($setopts['CURLOPT_SSL_VERIFYHOST'])) {
84
  $setopts['CURLOPT_SSL_VERIFYHOST'] = false;
85
+ }
86
+ if (!isset($setopts['CURLOPT_SSL_VERIFYPEER'])) {
87
  $setopts['CURLOPT_SSL_VERIFYPEER'] = false;
88
+ }
89
  }
90
+
91
  // Apply options
92
  foreach ($setopts as $name => $value) {
93
+ if (defined($name)) {
94
  @curl_setopt($ch, constant($name), $value);
95
+ }
96
  }
97
+
98
  // Now
99
  $response['timestamp'] = time();
100
+
101
  // Timer
102
  $time_start = microtime(true);
103
+
104
  // Retrieve response
105
  $response['data'] = @curl_exec($ch);
106
+
107
  // Time amount
108
  $response['time'] = microtime(true) - $time_start;
109
+
110
  // Copy error number
111
  $response['errno'] = (int) @curl_errno($ch);
112
+
113
  // Check info
114
  foreach ($getinfo as $info) {
115
+ if (defined($info)) {
116
  $response['info'][$info] = @curl_getinfo($ch, constant($info));
117
+ }
118
  }
119
+
120
  // Close connection
121
  @curl_close($ch);
122
+
123
  // Check error
124
  $response['error'] = ($response['errno'] > 0);
125
+
126
  // Done
127
  return $response;
128
  }
core/debug.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Debug functions
5
+ *
6
+ * @package WP Link Status
7
+ * @subpackage Core
8
+ */
9
+
10
+
11
+
12
+ // Load dependencies
13
+ require_once dirname(dirname(__FILE__)).'/constants.php';
14
+
15
+
16
+
17
+ /**
18
+ * Check debug flag
19
+ */
20
+ function wplnst_is_debug() {
21
+ return (defined('WPLNST_DEBUG') && !empty(WPLNST_DEBUG));
22
+ }
23
+
24
+
25
+
26
+ /**
27
+ * Output plugin debug
28
+ */
29
+ function wplnst_debug($message, $tag = '') {
30
+
31
+ // Check debug
32
+ if (!wplnst_is_debug()) {
33
+ return;
34
+ }
35
+
36
+ // Check output mode
37
+ $output = defined('WPLNST_DEBUG_OUTPUT')? WPLNST_DEBUG_OUTPUT : false;
38
+ if (empty($output) || !in_array($output, ['error_log', 'trace'])) {
39
+ $output = 'error_log';
40
+ }
41
+
42
+ // Default output
43
+ if ('error_log' == $output) {
44
+ error_log('WPLNST'.(empty($tag)? '' : ' ['.$tag.']').' - '.$message);
45
+
46
+ // Trace output
47
+ } elseif ('trace' == $output) {
48
+ wplnst_trace($message, $tag);
49
+ }
50
+ }
51
+
52
+
53
+
54
+ /**
55
+ * Appends a message to the trace file
56
+ */
57
+ function wplnst_trace($message, $tag) {
58
+ $path = dirname(dirname(dirname(dirname(__FILE__)))).'/wplnst_trace.txt';
59
+ @file_put_contents($path, date('Y-m-d h:i:s').' '.(empty($tag)? '' : '['.trim($tag).'] ').trim($message)."\n", FILE_APPEND);
60
+ }
core/module.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Module class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  abstract class WPLNST_Core_Module {
10
 
@@ -55,8 +55,9 @@ abstract class WPLNST_Core_Module {
55
  * Avoided use of get_called_class for PHP < 5.3 compatibility
56
  */
57
  protected static function get_instance($classname, $args = null) {
58
- if (!isset(self::$instances[$classname]))
59
  self::$instances[$classname] = new $classname($args);
 
60
  return self::$instances[$classname];
61
  }
62
 
@@ -132,11 +133,12 @@ abstract class WPLNST_Core_Module {
132
  * Check and initialize ajax respose
133
  */
134
  protected static function check_ajax_submit(&$response, $capability, $nonce = null) {
135
-
136
  // Check default output
137
- if (!isset($response))
138
  $response = self::default_ajax_response($nonce);
139
-
 
140
  // Check user capabilities
141
  if (!current_user_can($capability)) {
142
  $response['status'] = 'error';
@@ -149,7 +151,7 @@ abstract class WPLNST_Core_Module {
149
  $response['reason'] = __('Sorry, security verification error. Please reload this page and try again.', 'wplnst');
150
  return false;
151
  }
152
-
153
  // Submit Ok
154
  return true;
155
  }
1
  <?php
2
 
3
  /**
4
+ * Module class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  abstract class WPLNST_Core_Module {
10
 
55
  * Avoided use of get_called_class for PHP < 5.3 compatibility
56
  */
57
  protected static function get_instance($classname, $args = null) {
58
+ if (!isset(self::$instances[$classname])) {
59
  self::$instances[$classname] = new $classname($args);
60
+ }
61
  return self::$instances[$classname];
62
  }
63
 
133
  * Check and initialize ajax respose
134
  */
135
  protected static function check_ajax_submit(&$response, $capability, $nonce = null) {
136
+
137
  // Check default output
138
+ if (!isset($response)) {
139
  $response = self::default_ajax_response($nonce);
140
+ }
141
+
142
  // Check user capabilities
143
  if (!current_user_can($capability)) {
144
  $response['status'] = 'error';
151
  $response['reason'] = __('Sorry, security verification error. Please reload this page and try again.', 'wplnst');
152
  return false;
153
  }
154
+
155
  // Submit Ok
156
  return true;
157
  }
core/nonce/nonce.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Nonce class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Nonce {
10
 
@@ -28,20 +28,22 @@ class WPLNST_Core_Nonce {
28
  * Check valid nonce
29
  */
30
  public static function verify_nonce($nonce, $action = '') {
31
-
32
  // First check
33
  $nonce = (string) $nonce;
34
- if (empty($nonce))
35
  return false;
36
-
 
37
  // Time based "tick"
38
  $tick = self::nonce_tick();
39
-
40
  // Nonce generated 0-12 hours ago
41
  $expected = substr(self::get_hash($tick.'|'.$action.'|'.__FILE__), -12, 10);
42
- if (self::hash_equals($expected, $nonce))
43
  return 1;
44
-
 
45
  // Nonce generated 12-24 hours ago
46
  $expected = substr(self::get_hash(($tick - 1).'|'.$action.'|'.__FILE__), -12, 10);
47
  return self::hash_equals($expected, $nonce)? 2 : false;
@@ -63,9 +65,9 @@ class WPLNST_Core_Nonce {
63
  * Generates random number
64
  **/
65
  public static function get_rand( $min = 0, $max = 0 ) {
66
-
67
  global $wplnst_rnd_value;
68
-
69
  // Reset $rnd_value after 14 uses
70
  // 32(md5) + 40(sha1) + 40(sha1) / 8 = 14 random numbers from $rnd_value
71
  if ( strlen($wplnst_rnd_value) < 8 ) {
@@ -73,22 +75,23 @@ class WPLNST_Core_Nonce {
73
  $wplnst_rnd_value .= sha1($wplnst_rnd_value);
74
  $wplnst_rnd_value .= sha1($wplnst_rnd_value);
75
  }
76
-
77
  // Take the first 8 digits for our value
78
  $value = substr($wplnst_rnd_value, 0, 8);
79
-
80
  // Strip the first eight, leaving the remainder for the next call to wp_rand().
81
  $wplnst_rnd_value = substr($wplnst_rnd_value, 8);
82
-
83
  $value = abs(hexdec($value));
84
-
85
  // Some misconfigured 32bit environments (Entropy PHP, for example) truncate integers larger than PHP_INT_MAX to PHP_INT_MAX rather than overflowing them to floats.
86
  $max_random_number = 3000000000 === 2147483647 ? (float) "4294967295" : 4294967295; // 4294967295 = 0xffffffff
87
-
88
  // Reduce the value to be within the min - max range
89
- if ($max != 0)
90
  $value = $min + ($max - $min + 1) * $value / ($max_random_number + 1);
91
-
 
92
  return abs(intval($value));
93
  }
94
 
@@ -98,14 +101,27 @@ class WPLNST_Core_Nonce {
98
  * Password generation
99
  */
100
  public static function generate_password($length = 12, $special_chars = true, $extra_special_chars = false) {
 
 
101
  $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
102
- if ($special_chars)
 
 
103
  $chars .= '!@#$%^&*()';
104
- if ($extra_special_chars)
 
 
 
105
  $chars .= '-_ []{}<>~`+=,.;:/?|';
 
 
 
106
  $password = '';
107
- for ($i = 0; $i < $length; $i++)
108
  $password .= substr($chars, self::get_rand(0, strlen($chars) - 1), 1);
 
 
 
109
  return $password;
110
  }
111
 
@@ -124,12 +140,13 @@ class WPLNST_Core_Nonce {
124
  * Check salt file and constant
125
  */
126
  public static function salt_file_ready() {
127
-
128
  // Check if file exists
129
  $path = self::salt_file_path();
130
- if (!@file_exists($path) || !@is_readable($path))
131
  return false;
132
-
 
133
  // Require
134
  @require_once($path);
135
  return defined('WPLNST_SALT');
@@ -141,11 +158,20 @@ class WPLNST_Core_Nonce {
141
  * Attempt to create a salt file
142
  */
143
  public static function create_salt_file() {
 
 
144
  $path = self::salt_file_path();
145
- if (!@is_writable(dirname($path)))
146
  return false;
 
 
 
147
  $result = @file_put_contents($path, "<?php /* Generated by WP Link Status: PLEASE DO NOT REMOVE OR MODIFY THIS FILE */"."\n"."define('WPLNST_SALT', '".self::generate_password(64, false, false)."');");
 
 
148
  @chmod($path, 0644);
 
 
149
  return (false !== $result && @file_exists($path) && @is_readable($path));
150
  }
151
 
@@ -156,8 +182,9 @@ class WPLNST_Core_Nonce {
156
  */
157
  public static function remove_salt_file() {
158
  $path = self::salt_file_path();
159
- if (@file_exists($path))
160
  @unlink($path);
 
161
  }
162
 
163
 
@@ -181,17 +208,19 @@ class WPLNST_Core_Nonce {
181
  * Unique salt to hash strings
182
  */
183
  private static function get_salt() {
184
-
185
  // Process cache
186
  static $cached_salt;
187
- if (isset($cached_salt))
188
  return $cached_salt;
189
-
 
190
  // Salt from file
191
  $salt = self::get_salt_stored();
192
- if (empty($salt))
193
  $salt = php_uname().'|'.phpversion().'|'.__FILE__;
194
-
 
195
  // Store hash
196
  $cached_salt = md5($salt);
197
  return $cached_salt;
@@ -203,11 +232,12 @@ class WPLNST_Core_Nonce {
203
  * Return salt from config file
204
  */
205
  private static function get_salt_stored() {
206
-
207
  // Require file
208
- if (!defined('WPLNST_SALT'))
209
  self::require_salt_file();
210
-
 
211
  // Check constant
212
  return defined('WPLNST_SALT')? WPLNST_SALT : false;
213
  }
@@ -218,12 +248,13 @@ class WPLNST_Core_Nonce {
218
  * Check if file exists and require config file
219
  */
220
  private static function require_salt_file() {
221
-
222
  // Check if file exists
223
  $path = self::salt_file_path();
224
- if (!@file_exists($path) || !@is_readable($path))
225
  return false;
226
-
 
227
  // Require
228
  @require_once($path);
229
  }
@@ -244,34 +275,37 @@ class WPLNST_Core_Nonce {
244
  * Wrapper for hash_hmac function
245
  */
246
  private static function hash_hmac($algo, $data, $key, $raw_output = false) {
247
-
248
  // Check existing function
249
  if (function_exists('hash_hmac')) {
250
  return hash_hmac($algo, $data, $key, $raw_output);
251
-
252
  // From WP
253
  } else {
254
-
255
  $packs = array('md5' => 'H32', 'sha1' => 'H40');
256
-
257
- if (!isset($packs[$algo]))
258
  return false;
259
-
 
260
  $pack = $packs[$algo];
261
-
262
- if (strlen($key) > 64)
263
  $key = pack($pack, $algo($key));
264
-
 
265
  $key = str_pad($key, 64, chr(0));
266
-
267
  $ipad = (substr($key, 0, 64) ^ str_repeat(chr(0x36), 64));
268
  $opad = (substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64));
269
-
270
  $hmac = $algo($opad.pack($pack, $algo($ipad.$data)));
271
-
272
- if ($raw_output)
273
  return pack($pack, $hmac);
274
-
 
275
  return $hmac;
276
  }
277
  }
@@ -282,25 +316,26 @@ class WPLNST_Core_Nonce {
282
  * Wrapper for hash_equals function
283
  */
284
  private static function hash_equals($a, $b) {
285
-
286
  // Check existing function
287
  if (function_exists('hash_equals')) {
288
  return hash_equals($a, $b);
289
-
290
  // From WP
291
  } else {
292
-
293
  $a_length = strlen($a);
294
- if ($a_length !== strlen($b))
295
  return false;
296
-
 
297
  $result = 0;
298
-
299
  // Do not attempt to "optimize" this.
300
  for ($i = 0; $i < $a_length; $i++) {
301
  $result |= ord($a[$i]) ^ ord($b[$i]);
302
  }
303
-
304
  return $result === 0;
305
  }
306
  }
1
  <?php
2
 
3
  /**
4
+ * Nonce class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Nonce {
10
 
28
  * Check valid nonce
29
  */
30
  public static function verify_nonce($nonce, $action = '') {
31
+
32
  // First check
33
  $nonce = (string) $nonce;
34
+ if (empty($nonce)) {
35
  return false;
36
+ }
37
+
38
  // Time based "tick"
39
  $tick = self::nonce_tick();
40
+
41
  // Nonce generated 0-12 hours ago
42
  $expected = substr(self::get_hash($tick.'|'.$action.'|'.__FILE__), -12, 10);
43
+ if (self::hash_equals($expected, $nonce)) {
44
  return 1;
45
+ }
46
+
47
  // Nonce generated 12-24 hours ago
48
  $expected = substr(self::get_hash(($tick - 1).'|'.$action.'|'.__FILE__), -12, 10);
49
  return self::hash_equals($expected, $nonce)? 2 : false;
65
  * Generates random number
66
  **/
67
  public static function get_rand( $min = 0, $max = 0 ) {
68
+
69
  global $wplnst_rnd_value;
70
+
71
  // Reset $rnd_value after 14 uses
72
  // 32(md5) + 40(sha1) + 40(sha1) / 8 = 14 random numbers from $rnd_value
73
  if ( strlen($wplnst_rnd_value) < 8 ) {
75
  $wplnst_rnd_value .= sha1($wplnst_rnd_value);
76
  $wplnst_rnd_value .= sha1($wplnst_rnd_value);
77
  }
78
+
79
  // Take the first 8 digits for our value
80
  $value = substr($wplnst_rnd_value, 0, 8);
81
+
82
  // Strip the first eight, leaving the remainder for the next call to wp_rand().
83
  $wplnst_rnd_value = substr($wplnst_rnd_value, 8);
84
+
85
  $value = abs(hexdec($value));
86
+
87
  // Some misconfigured 32bit environments (Entropy PHP, for example) truncate integers larger than PHP_INT_MAX to PHP_INT_MAX rather than overflowing them to floats.
88
  $max_random_number = 3000000000 === 2147483647 ? (float) "4294967295" : 4294967295; // 4294967295 = 0xffffffff
89
+
90
  // Reduce the value to be within the min - max range
91
+ if ($max != 0) {
92
  $value = $min + ($max - $min + 1) * $value / ($max_random_number + 1);
93
+ }
94
+
95
  return abs(intval($value));
96
  }
97
 
101
  * Password generation
102
  */
103
  public static function generate_password($length = 12, $special_chars = true, $extra_special_chars = false) {
104
+
105
+ // Alphabet
106
  $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
107
+
108
+ // Add special
109
+ if ($special_chars) {
110
  $chars .= '!@#$%^&*()';
111
+ }
112
+
113
+ // Extra chars
114
+ if ($extra_special_chars) {
115
  $chars .= '-_ []{}<>~`+=,.;:/?|';
116
+ }
117
+
118
+ // Generate password
119
  $password = '';
120
+ for ($i = 0; $i < $length; $i++) {
121
  $password .= substr($chars, self::get_rand(0, strlen($chars) - 1), 1);
122
+ }
123
+
124
+ // Done
125
  return $password;
126
  }
127
 
140
  * Check salt file and constant
141
  */
142
  public static function salt_file_ready() {
143
+
144
  // Check if file exists
145
  $path = self::salt_file_path();
146
+ if (!@file_exists($path) || !@is_readable($path)) {
147
  return false;
148
+ }
149
+
150
  // Require
151
  @require_once($path);
152
  return defined('WPLNST_SALT');
158
  * Attempt to create a salt file
159
  */
160
  public static function create_salt_file() {
161
+
162
+ // Check directory permissions
163
  $path = self::salt_file_path();
164
+ if (!@is_writable(dirname($path))) {
165
  return false;
166
+ }
167
+
168
+ // Attempt to write the file
169
  $result = @file_put_contents($path, "<?php /* Generated by WP Link Status: PLEASE DO NOT REMOVE OR MODIFY THIS FILE */"."\n"."define('WPLNST_SALT', '".self::generate_password(64, false, false)."');");
170
+
171
+ // Set permissions
172
  @chmod($path, 0644);
173
+
174
+ // Done
175
  return (false !== $result && @file_exists($path) && @is_readable($path));
176
  }
177
 
182
  */
183
  public static function remove_salt_file() {
184
  $path = self::salt_file_path();
185
+ if (@file_exists($path)) {
186
  @unlink($path);
187
+ }
188
  }
189
 
190
 
208
  * Unique salt to hash strings
209
  */
210
  private static function get_salt() {
211
+
212
  // Process cache
213
  static $cached_salt;
214
+ if (isset($cached_salt)) {
215
  return $cached_salt;
216
+ }
217
+
218
  // Salt from file
219
  $salt = self::get_salt_stored();
220
+ if (empty($salt)) {
221
  $salt = php_uname().'|'.phpversion().'|'.__FILE__;
222
+ }
223
+
224
  // Store hash
225
  $cached_salt = md5($salt);
226
  return $cached_salt;
232
  * Return salt from config file
233
  */
234
  private static function get_salt_stored() {
235
+
236
  // Require file
237
+ if (!defined('WPLNST_SALT')) {
238
  self::require_salt_file();
239
+ }
240
+
241
  // Check constant
242
  return defined('WPLNST_SALT')? WPLNST_SALT : false;
243
  }
248
  * Check if file exists and require config file
249
  */
250
  private static function require_salt_file() {
251
+
252
  // Check if file exists
253
  $path = self::salt_file_path();
254
+ if (!@file_exists($path) || !@is_readable($path)) {
255
  return false;
256
+ }
257
+
258
  // Require
259
  @require_once($path);
260
  }
275
  * Wrapper for hash_hmac function
276
  */
277
  private static function hash_hmac($algo, $data, $key, $raw_output = false) {
278
+
279
  // Check existing function
280
  if (function_exists('hash_hmac')) {
281
  return hash_hmac($algo, $data, $key, $raw_output);
282
+
283
  // From WP
284
  } else {
285
+
286
  $packs = array('md5' => 'H32', 'sha1' => 'H40');
287
+
288
+ if (!isset($packs[$algo])) {
289
  return false;
290
+ }
291
+
292
  $pack = $packs[$algo];
293
+
294
+ if (strlen($key) > 64) {
295
  $key = pack($pack, $algo($key));
296
+ }
297
+
298
  $key = str_pad($key, 64, chr(0));
299
+
300
  $ipad = (substr($key, 0, 64) ^ str_repeat(chr(0x36), 64));
301
  $opad = (substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64));
302
+
303
  $hmac = $algo($opad.pack($pack, $algo($ipad.$data)));
304
+
305
+ if ($raw_output) {
306
  return pack($pack, $hmac);
307
+ }
308
+
309
  return $hmac;
310
  }
311
  }
316
  * Wrapper for hash_equals function
317
  */
318
  private static function hash_equals($a, $b) {
319
+
320
  // Check existing function
321
  if (function_exists('hash_equals')) {
322
  return hash_equals($a, $b);
323
+
324
  // From WP
325
  } else {
326
+
327
  $a_length = strlen($a);
328
+ if ($a_length !== strlen($b)) {
329
  return false;
330
+ }
331
+
332
  $result = 0;
333
+
334
  // Do not attempt to "optimize" this.
335
  for ($i = 0; $i < $a_length; $i++) {
336
  $result |= ord($a[$i]) ^ ord($b[$i]);
337
  }
338
+
339
  return $result === 0;
340
  }
341
  }
core/notify.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Notify class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Notify {
10
 
@@ -14,15 +14,15 @@ class WPLNST_Core_Notify {
14
  * Send a notification of scan completed
15
  */
16
  public static function completed($scan) {
17
-
18
  // Get current notifications
19
  $notifications = self::get_notifications();
20
  if (!in_array($scan->id, $notifications)) {
21
-
22
  // Add scan to notifications
23
  $notifications[] = $scan->id;
24
  self::set_notifications($notifications);
25
-
26
  // Spawn admin ajax URL
27
  wplnst_require('core', 'curl');
28
  WPLNST_Core_CURL::spawn(array('CURLOPT_URL' => add_query_arg(array(
@@ -38,55 +38,62 @@ class WPLNST_Core_Notify {
38
  * Check for pending notifications
39
  */
40
  public static function check() {
41
-
42
  // Retrieve notifications
43
  $notifications = self::get_notifications();
44
- if (empty($notifications))
45
  return;
46
-
 
47
  // Extract first element
48
  $scan_id = (int) array_shift($notifications);
49
  self::set_notifications($notifications);
50
-
51
  // Check identifier
52
- if (!$scan_id > 0)
53
  return;
54
-
 
55
  // Check scan
56
  global $wpdb;
57
  $scan_row = $wpdb->get_row($wpdb->prepare('SELECT name, config FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
58
- if (empty($scan_row) || !is_object($scan_row))
59
  return;
60
-
 
61
  // Extract configuration
62
  $config = @json_decode($scan_row->config, true);
63
- if (empty($config) || !is_array($config))
64
  return;
65
-
 
66
  // Initialize
67
  $emails = array();
68
-
69
  // Default e-mail
70
  if (isset($config['notify_default']) && true === $config['notify_default']) {
71
  $admin_email = get_option('admin_email');
72
- if (!empty($admin_email) && is_email($admin_email))
73
  $emails[] = $admin_email;
 
74
  }
75
-
76
  // New addresses
77
  if (isset($config['notify_address']) && true === $config['notify_address'] && !empty($config['notify_address_email'])) {
78
  $addresses = str_replace(',', ';', $config['notify_address_email']);
79
  $addresses = explode(';', $addresses);
80
  foreach ($addresses as $address) {
81
- if (!empty($address) && is_email($address))
82
  $emails[] = $address;
 
83
  }
84
  }
85
-
86
  // Check collection
87
- if (empty($emails))
88
  return;
89
-
 
90
  // Send
91
  $result = wp_mail(array_unique($emails), __('WP Link Status scan completed', 'wplnst'),
92
  sprintf(__('
1
  <?php
2
 
3
  /**
4
+ * Notify class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Notify {
10
 
14
  * Send a notification of scan completed
15
  */
16
  public static function completed($scan) {
17
+
18
  // Get current notifications
19
  $notifications = self::get_notifications();
20
  if (!in_array($scan->id, $notifications)) {
21
+
22
  // Add scan to notifications
23
  $notifications[] = $scan->id;
24
  self::set_notifications($notifications);
25
+
26
  // Spawn admin ajax URL
27
  wplnst_require('core', 'curl');
28
  WPLNST_Core_CURL::spawn(array('CURLOPT_URL' => add_query_arg(array(
38
  * Check for pending notifications
39
  */
40
  public static function check() {
41
+
42
  // Retrieve notifications
43
  $notifications = self::get_notifications();
44
+ if (empty($notifications)) {
45
  return;
46
+ }
47
+
48
  // Extract first element
49
  $scan_id = (int) array_shift($notifications);
50
  self::set_notifications($notifications);
51
+
52
  // Check identifier
53
+ if (!$scan_id > 0) {
54
  return;
55
+ }
56
+
57
  // Check scan
58
  global $wpdb;
59
  $scan_row = $wpdb->get_row($wpdb->prepare('SELECT name, config FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
60
+ if (empty($scan_row) || !is_object($scan_row)) {
61
  return;
62
+ }
63
+
64
  // Extract configuration
65
  $config = @json_decode($scan_row->config, true);
66
+ if (empty($config) || !is_array($config)) {
67
  return;
68
+ }
69
+
70
  // Initialize
71
  $emails = array();
72
+
73
  // Default e-mail
74
  if (isset($config['notify_default']) && true === $config['notify_default']) {
75
  $admin_email = get_option('admin_email');
76
+ if (!empty($admin_email) && is_email($admin_email)) {
77
  $emails[] = $admin_email;
78
+ }
79
  }
80
+
81
  // New addresses
82
  if (isset($config['notify_address']) && true === $config['notify_address'] && !empty($config['notify_address_email'])) {
83
  $addresses = str_replace(',', ';', $config['notify_address_email']);
84
  $addresses = explode(';', $addresses);
85
  foreach ($addresses as $address) {
86
+ if (!empty($address) && is_email($address)) {
87
  $emails[] = $address;
88
+ }
89
  }
90
  }
91
+
92
  // Check collection
93
+ if (empty($emails)) {
94
  return;
95
+ }
96
+
97
  // Send
98
  $result = wp_mail(array_unique($emails), __('WP Link Status scan completed', 'wplnst'),
99
  sprintf(__('
core/plugin.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Plugin class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Plugin {
10
 
@@ -18,7 +18,7 @@ class WPLNST_Core_Plugin {
18
  /**
19
  * Plugin
20
  */
21
- const title = 'WP Link Status';
22
  const slug = 'wp-link-status';
23
  const capability = 'manage_options';
24
 
1
  <?php
2
 
3
  /**
4
+ * Plugin class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Plugin {
10
 
18
  /**
19
  * Plugin
20
  */
21
+ const title = 'WP Link Status';
22
  const slug = 'wp-link-status';
23
  const capability = 'manage_options';
24
 
core/register.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Register class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Register {
10
 
@@ -14,17 +14,18 @@ class WPLNST_Core_Register {
14
  * Plugin activation process
15
  */
16
  public static function activation() {
17
-
18
  // Check salt file
19
  WPLNST_Core_Nonce::check_salt_file();
20
-
21
  // Load scheme library
22
  wplnst_require('core', 'scheme');
23
-
24
  // Check plugins tables
25
- if (false !== ($tables = WPLNST_Core_Scheme::check_tables()))
26
  WPLNST_Core_Scheme::create_tables($tables);
27
-
 
28
  // Check scheme upgrade
29
  WPLNST_Core_Scheme::upgrade();
30
  }
@@ -44,23 +45,24 @@ class WPLNST_Core_Register {
44
  * Uninstall plugin data
45
  */
46
  public static function uninstall() {
47
-
48
  // Uninstall info first
49
- if (!wplnst_get_bsetting('uninstall_data'))
50
  return;
51
-
 
52
  // Remove salt file
53
  WPLNST_Core_Nonce::remove_salt_file();
54
-
55
  // Remove user meta
56
  $user_id = get_current_user_id();
57
  delete_user_meta($user_id, 'wplnst_advanced_search');
58
  delete_user_meta($user_id, 'wplnst_scans_per_page');
59
  delete_user_meta($user_id, 'wplnst_scan_results_per_page');
60
-
61
  // Remove plugin options
62
  WPLNST_Core_Settings::delete_all_options();
63
-
64
  // Remove scheme tables
65
  wplnst_require('core', 'scheme');
66
  WPLNST_Core_Scheme::drop_tables();
1
  <?php
2
 
3
  /**
4
+ * Register class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Register {
10
 
14
  * Plugin activation process
15
  */
16
  public static function activation() {
17
+
18
  // Check salt file
19
  WPLNST_Core_Nonce::check_salt_file();
20
+
21
  // Load scheme library
22
  wplnst_require('core', 'scheme');
23
+
24
  // Check plugins tables
25
+ if (false !== ($tables = WPLNST_Core_Scheme::check_tables())) {
26
  WPLNST_Core_Scheme::create_tables($tables);
27
+ }
28
+
29
  // Check scheme upgrade
30
  WPLNST_Core_Scheme::upgrade();
31
  }
45
  * Uninstall plugin data
46
  */
47
  public static function uninstall() {
48
+
49
  // Uninstall info first
50
+ if (!wplnst_get_bsetting('uninstall_data')) {
51
  return;
52
+ }
53
+
54
  // Remove salt file
55
  WPLNST_Core_Nonce::remove_salt_file();
56
+
57
  // Remove user meta
58
  $user_id = get_current_user_id();
59
  delete_user_meta($user_id, 'wplnst_advanced_search');
60
  delete_user_meta($user_id, 'wplnst_scans_per_page');
61
  delete_user_meta($user_id, 'wplnst_scan_results_per_page');
62
+
63
  // Remove plugin options
64
  WPLNST_Core_Settings::delete_all_options();
65
+
66
  // Remove scheme tables
67
  wplnst_require('core', 'scheme');
68
  WPLNST_Core_Scheme::drop_tables();
core/requests/class-json.php CHANGED
File without changes
core/requests/http.php CHANGED
@@ -22,77 +22,96 @@ class WPLNST_Core_HTTP_Request {
22
  * Start request process
23
  */
24
  public static function start() {
25
-
26
-
27
-
28
  /* Initialization */
29
-
 
 
 
30
  // Default timezone
31
  date_default_timezone_set('UTC');
32
-
33
  // Check basic arguments
34
- if (!empty($_GET) || empty($_POST) || empty($_POST['url']) || empty($_POST['url_id']) || empty($_POST['connect_timeout']) || empty($_POST['request_timeout']) || empty($_POST['max_download']) || empty($_POST['nonce']) || empty($_POST['hash']))
 
35
  self::terminate();
36
-
 
37
  // Check URL
38
  $url = $_POST['url'];
39
- if (empty($url) || (0 !== stripos($url, 'http://') && 0 !== stripos($url, 'https://') && 0 !== stripos($url, 'ftp://')))
 
40
  self::terminate();
41
-
 
42
  // Check URL id
43
  $url_id = (int) $_POST['url_id'];
44
- if (empty($url_id))
 
45
  self::terminate();
46
-
 
47
  // Check back URL
48
  $back_url = empty($_POST['back_url'])? false : trim($_POST['back_url']);
49
- if (!empty($back_url) && (0 !== stripos($back_url, 'http://') && 0 !== stripos($back_url, 'https://')))
 
50
  self::terminate();
51
-
 
52
  // Check connect timeout
53
  $connect_timeout = (int) $_POST['connect_timeout'];
54
- if (empty($connect_timeout))
 
55
  self::terminate();
56
-
 
57
  // Check request timeout
58
  $request_timeout = (int) $_POST['request_timeout'];
59
- if (empty($request_timeout))
 
60
  self::terminate();
61
-
 
62
  // Check max download
63
  global $max_download, $max_download_done;
64
  $max_download = (int) $_POST['max_download'];
65
- if (empty($max_download))
 
66
  self::terminate();
67
-
 
68
  // Check only headers
69
  global $only_headers, $only_headers_done;
70
  $only_headers = (isset($_POST['only_headers']) && '1' == $_POST['only_headers']);
71
-
72
  // Load nonce library
73
  require(dirname(dirname(__FILE__)).'/nonce/nonce.php');
74
-
75
  // Verify nonce for this URL hash
76
- if (!WPLNST_Core_Nonce::verify_nonce($_POST['nonce'], $_POST['hash']))
 
77
  self::terminate();
78
-
 
79
  // Load cURL wrapper library
80
  require(dirname(dirname(__FILE__)).'/curl.php');
81
-
82
  // User Agent string
83
  $user_agent = empty($_POST['user_agent'])? '' : $_POST['user_agent'];
84
-
85
-
86
-
87
  /* URL HTTP status */
88
-
89
  // No timeout
90
  set_time_limit(0);
91
-
92
  // Initialize globals
93
  global $wplnst_http_response;
94
  $wplnst_http_response = '';
95
-
96
  // Prepare CURL options
97
  $curlopts = array(
98
  'CURLOPT_URL' => $url,
@@ -108,40 +127,49 @@ class WPLNST_Core_HTTP_Request {
108
  'CURLOPT_USERAGENT' => $user_agent,
109
  'CURLOPT_WRITEFUNCTION' => 'wplnst_http_read_stream',
110
  );
111
-
 
 
 
112
  // Do the request
113
  $response = WPLNST_Core_CURL::request($curlopts, array('CURLINFO_HEADER_OUT', 'CURLINFO_TOTAL_TIME', 'CURLINFO_SIZE_DOWNLOAD', 'CURLINFO_HEADER_SIZE'));
114
-
 
 
 
115
  // Check request headers
116
  $headers_request = isset($response['info']['CURLINFO_HEADER_OUT'])? $response['info']['CURLINFO_HEADER_OUT'] : '';
117
-
118
  // Check total time
119
  $total_time = isset($response['info']['CURLINFO_TOTAL_TIME'])? (int) $response['info']['CURLINFO_TOTAL_TIME'] : false;
120
- if (empty($total_time))
121
  $total_time = $response['time'];
122
-
 
123
  // Total size
124
  $total_bytes = isset($response['info']['CURLINFO_SIZE_DOWNLOAD'])? (int) $response['info']['CURLINFO_SIZE_DOWNLOAD'] : false;
125
- if (empty($total_bytes))
126
  $total_bytes = strlen($wplnst_http_response);
127
-
 
128
  // Headers size
129
  $headers_size = isset($response['info']['CURLINFO_HEADER_SIZE'])? (int) $response['info']['CURLINFO_HEADER_SIZE'] : false;
130
  if (empty($headers_size)) {
131
  $headers_pos = strpos($wplnst_http_response, "\r\n\r\n");
132
  $headers_size = (false === $headers_pos)? $total_bytes : $headers_pos + 4;
133
  }
134
-
135
  // Extract headers (trim to avoid conflicts with this script in API mode)
136
  $wplnst_http_headers = trim(substr($wplnst_http_response, 0, $headers_size));
137
-
138
  // Check errno exception when aborted with this plugin
139
- if ('23' == $response['errno'] && (!empty($max_download_done) || !empty($only_headers_done)))
140
  $response['errno'] = 0;
141
-
142
-
 
143
  /* Back to WP */
144
-
145
  // Populate POST fields
146
  $postfields = array(
147
  'url_id' => $url_id,
@@ -153,33 +181,39 @@ class WPLNST_Core_HTTP_Request {
153
  'curl_errno' => $response['errno'],
154
  'timestamp' => $response['timestamp'],
155
  );
156
-
157
  // Aditional body field
158
- if (!empty($_POST['return_body']) && '1' == $_POST['return_body'])
159
  $postfields['body'] = substr($wplnst_http_response, $headers_size);
160
-
 
161
  // Check back URL
162
  if (!empty($back_url)) {
163
-
164
  // Debug point
165
- self::debug('script back start');
166
-
167
  // Spawn back URL call
168
- WPLNST_Core_CURL::spawn(array(
169
- 'CURLOPT_URL' => $back_url,
170
- 'CURLOPT_USERAGENT' => 'WPLNST HTTP Requests script',
171
- 'CURLOPT_POST' => true,
172
- 'CURLOPT_POSTFIELDS' => http_build_query($postfields, null, '&'),
173
- 'CURLOPT_HTTPHEADER' => array('Content-Type: application/x-www-form-urlencoded; charset=utf-8'),
 
 
174
  ));
175
-
176
  // Debug point
177
- self::debug('script back end');
178
-
179
  // End
180
  self::terminate();
181
  }
182
-
 
 
 
183
  // End with post data
184
  self::terminate($postfields);
185
  }
@@ -195,16 +229,16 @@ class WPLNST_Core_HTTP_Request {
195
  * Ends execution
196
  */
197
  private static function terminate($output = array()) {
198
-
199
  // Initialize
200
  $dump = '';
201
-
202
- // Check array output
203
  if (!empty($output) && is_array($output)) {
204
-
205
  // JSON response
206
  @header('Content-Type: application/json');
207
-
208
  // Dump data
209
  $dump = self::json_encode(array(
210
  'status' => 'ok',
@@ -218,13 +252,13 @@ class WPLNST_Core_HTTP_Request {
218
  @header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
219
  @header('Cache-Control: post-check=0, pre-check=0', false);
220
  @header('Pragma: no-cache');
221
-
222
  // Avoid indexation
223
  @header('X-Robots-Tag: noindex');
224
-
225
  // Debug point
226
  self::debug('script terminate');
227
-
228
  // End
229
  die($dump);
230
  }
@@ -235,28 +269,29 @@ class WPLNST_Core_HTTP_Request {
235
  * A driver or wrapper for JSON encode
236
  */
237
  private static function json_encode($string) {
238
-
239
  // Check native function
240
  if (function_exists('json_encode')) {
241
  return @json_encode($string);
242
-
243
  // Other
244
  } else {
245
-
246
  // Globals
247
  global $wp_json;
248
-
249
  // Check current instance
250
  if (empty($wp_json) || !($wp_json instanceof Services_JSON)) {
251
-
252
  // Include file
253
  @require_once(dirname(__FILE__).'/class-json.php');
254
-
255
  // Create new object
256
- if (class_exists('Services_JSON'))
257
  $wp_json = new Services_JSON();
 
258
  }
259
-
260
  // Check object
261
  return (!empty($wp_json) && $wp_json instanceof Services_JSON)? $wp_json->encodeUnsafe($string) : false;
262
  }
@@ -264,83 +299,20 @@ class WPLNST_Core_HTTP_Request {
264
 
265
 
266
 
267
- // Debug
268
- // ---------------------------------------------------------------------------------------------------
269
-
270
-
271
-
272
  /**
273
  * Debug output
274
  */
275
  private static function debug($message) {
276
-
277
- // Initialize
278
- static $debug_info;
279
- if (!isset($debug_info))
280
- $debug_info = self::debug_info();
281
-
282
- // Check debug
283
- if (false === $debug_info)
284
- return;
285
-
286
- // Prefix
287
- $prefix = '';
288
- if (!empty($debug_info['scan_id'])) {
289
- $prefix = 'scan '.$debug_info['scan_id'];
290
- if (!empty($debug_info['thread_id']))
291
- $prefix .= ' - thread '.$debug_info['thread_id'];
292
- $prefix .= ' ';
293
- }
294
-
295
- // Output
296
- error_log('WPLNST - '.$prefix.'[http] '.$message);
297
- }
298
 
299
-
300
-
301
- /**
302
- * Debug info check
303
- */
304
- private static function debug_info() {
305
-
306
- // Check debug argument
307
- if (empty($_POST['debug']) || '1' != $_POST['debug'])
308
- return false;
309
-
310
- // Initialize
311
- $debug_info = array();
312
-
313
- // Check back URL
314
- if (!empty($_POST['back_url'])) {
315
-
316
- // Analyze back URL
317
- $info = explode('&wplnst_', str_replace('?wplnst_', '&wplnst_', $_POST['back_url']));
318
-
319
- // Enum elements
320
- foreach ($info as $pair) {
321
-
322
- // Check a pair
323
- $pair = explode('=', $pair);
324
- if (2 == count($pair)) {
325
-
326
- // Scan
327
- if ('crawl' == $pair[0]) {
328
- $scan_id = (int) $pair[1];
329
- if ($scan_id > 0)
330
- $debug_info['scan_id'] = $scan_id;
331
-
332
- // Thread
333
- } elseif ('thread' == $pair[0]) {
334
- $thread_id = (int) $pair[1];
335
- if ($thread_id > 0)
336
- $debug_info['thread_id'] = $thread_id;
337
- }
338
- }
339
- }
340
  }
341
-
342
- // Done
343
- return $debug_info;
344
  }
345
 
346
 
@@ -358,42 +330,43 @@ class WPLNST_Core_HTTP_Request {
358
  * Response callback function
359
  */
360
  function wplnst_http_read_stream($ch, $line) {
361
-
362
  // Globals
363
  global $wplnst_http_response, $max_download, $max_download_done, $only_headers, $only_headers_done;
364
-
365
  // Current lengths
366
  $line_length = strlen($line);
367
  $total_length = strlen($wplnst_http_response);
368
-
369
  // Check overflow
370
  if (($total_length + $line_length) > $max_download) {
371
-
372
  // Check available size
373
  $available = $max_download - $total_length;
374
- if ($available > 0)
375
  $wplnst_http_response .= substr($line, 0, $available);
376
-
 
377
  // Max download achieved
378
  $max_download_done = true;
379
-
380
  // End
381
  return 0;
382
  }
383
-
384
  // Add new chunk
385
  $wplnst_http_response .= $line;
386
-
387
  // Check only headers
388
  if ($only_headers && false !== strpos($wplnst_http_response, "\r\n\r\n")) {
389
-
390
  // Headers achieved
391
  $only_headers_done = true;
392
-
393
  // End
394
  return 0;
395
  }
396
-
397
  // Done
398
  return strlen($line);
399
  }
22
  * Start request process
23
  */
24
  public static function start() {
25
+
26
+
27
+
28
  /* Initialization */
29
+
30
+ // Debug point
31
+ self::debug('start');
32
+
33
  // Default timezone
34
  date_default_timezone_set('UTC');
35
+
36
  // Check basic arguments
37
+ if (!empty($_GET) || empty($_POST) || empty($_POST['url']) || empty($_POST['url_id']) || empty($_POST['connect_timeout']) || empty($_POST['request_timeout']) || empty($_POST['max_download']) || empty($_POST['nonce']) || empty($_POST['hash'])) {
38
+ self::debug('error args');
39
  self::terminate();
40
+ }
41
+
42
  // Check URL
43
  $url = $_POST['url'];
44
+ if (empty($url) || (0 !== stripos($url, 'http://') && 0 !== stripos($url, 'https://') && 0 !== stripos($url, 'ftp://'))) {
45
+ self::debug('error protocol');
46
  self::terminate();
47
+ }
48
+
49
  // Check URL id
50
  $url_id = (int) $_POST['url_id'];
51
+ if (empty($url_id)) {
52
+ self::debug('error url_id');
53
  self::terminate();
54
+ }
55
+
56
  // Check back URL
57
  $back_url = empty($_POST['back_url'])? false : trim($_POST['back_url']);
58
+ if (!empty($back_url) && (0 !== stripos($back_url, 'http://') && 0 !== stripos($back_url, 'https://'))) {
59
+ self::debug('error back_url: '.$back_url);
60
  self::terminate();
61
+ }
62
+
63
  // Check connect timeout
64
  $connect_timeout = (int) $_POST['connect_timeout'];
65
+ if (empty($connect_timeout)) {
66
+ self::debug('error connect timeout');
67
  self::terminate();
68
+ }
69
+
70
  // Check request timeout
71
  $request_timeout = (int) $_POST['request_timeout'];
72
+ if (empty($request_timeout)) {
73
+ self::debug('error request timeout');
74
  self::terminate();
75
+ }
76
+
77
  // Check max download
78
  global $max_download, $max_download_done;
79
  $max_download = (int) $_POST['max_download'];
80
+ if (empty($max_download)) {
81
+ self::debug('error max download');
82
  self::terminate();
83
+ }
84
+
85
  // Check only headers
86
  global $only_headers, $only_headers_done;
87
  $only_headers = (isset($_POST['only_headers']) && '1' == $_POST['only_headers']);
88
+
89
  // Load nonce library
90
  require(dirname(dirname(__FILE__)).'/nonce/nonce.php');
91
+
92
  // Verify nonce for this URL hash
93
+ if (!WPLNST_Core_Nonce::verify_nonce($_POST['nonce'], $_POST['hash'])) {
94
+ self::debug('error nonce hash');
95
  self::terminate();
96
+ }
97
+
98
  // Load cURL wrapper library
99
  require(dirname(dirname(__FILE__)).'/curl.php');
100
+
101
  // User Agent string
102
  $user_agent = empty($_POST['user_agent'])? '' : $_POST['user_agent'];
103
+
104
+
105
+
106
  /* URL HTTP status */
107
+
108
  // No timeout
109
  set_time_limit(0);
110
+
111
  // Initialize globals
112
  global $wplnst_http_response;
113
  $wplnst_http_response = '';
114
+
115
  // Prepare CURL options
116
  $curlopts = array(
117
  'CURLOPT_URL' => $url,
127
  'CURLOPT_USERAGENT' => $user_agent,
128
  'CURLOPT_WRITEFUNCTION' => 'wplnst_http_read_stream',
129
  );
130
+
131
+ // Debug point
132
+ self::debug('before curl request');
133
+
134
  // Do the request
135
  $response = WPLNST_Core_CURL::request($curlopts, array('CURLINFO_HEADER_OUT', 'CURLINFO_TOTAL_TIME', 'CURLINFO_SIZE_DOWNLOAD', 'CURLINFO_HEADER_SIZE'));
136
+
137
+ // Debug point
138
+ self::debug('after curl request');
139
+
140
  // Check request headers
141
  $headers_request = isset($response['info']['CURLINFO_HEADER_OUT'])? $response['info']['CURLINFO_HEADER_OUT'] : '';
142
+
143
  // Check total time
144
  $total_time = isset($response['info']['CURLINFO_TOTAL_TIME'])? (int) $response['info']['CURLINFO_TOTAL_TIME'] : false;
145
+ if (empty($total_time)) {
146
  $total_time = $response['time'];
147
+ }
148
+
149
  // Total size
150
  $total_bytes = isset($response['info']['CURLINFO_SIZE_DOWNLOAD'])? (int) $response['info']['CURLINFO_SIZE_DOWNLOAD'] : false;
151
+ if (empty($total_bytes)) {
152
  $total_bytes = strlen($wplnst_http_response);
153
+ }
154
+
155
  // Headers size
156
  $headers_size = isset($response['info']['CURLINFO_HEADER_SIZE'])? (int) $response['info']['CURLINFO_HEADER_SIZE'] : false;
157
  if (empty($headers_size)) {
158
  $headers_pos = strpos($wplnst_http_response, "\r\n\r\n");
159
  $headers_size = (false === $headers_pos)? $total_bytes : $headers_pos + 4;
160
  }
161
+
162
  // Extract headers (trim to avoid conflicts with this script in API mode)
163
  $wplnst_http_headers = trim(substr($wplnst_http_response, 0, $headers_size));
164
+
165
  // Check errno exception when aborted with this plugin
166
+ if ('23' == $response['errno'] && (!empty($max_download_done) || !empty($only_headers_done))) {
167
  $response['errno'] = 0;
168
+ }
169
+
170
+
171
  /* Back to WP */
172
+
173
  // Populate POST fields
174
  $postfields = array(
175
  'url_id' => $url_id,
181
  'curl_errno' => $response['errno'],
182
  'timestamp' => $response['timestamp'],
183
  );
184
+
185
  // Aditional body field
186
+ if (!empty($_POST['return_body']) && '1' == $_POST['return_body']) {
187
  $postfields['body'] = substr($wplnst_http_response, $headers_size);
188
+ }
189
+
190
  // Check back URL
191
  if (!empty($back_url)) {
192
+
193
  // Debug point
194
+ self::debug('back to '.$back_url);
195
+
196
  // Spawn back URL call
197
+ $response = WPLNST_Core_CURL::spawn(array(
198
+ 'CURLOPT_URL' => $back_url,
199
+ 'CURLOPT_USERAGENT' => 'WPLNST HTTP Requests script',
200
+ 'CURLOPT_POST' => true,
201
+ 'CURLOPT_POSTFIELDS' => http_build_query($postfields, null, '&'),
202
+ 'CURLOPT_HTTPHEADER' => array('Content-Type: application/x-www-form-urlencoded; charset=utf-8'),
203
+ 'CURLOPT_CONNECTTIMEOUT' => 5,
204
+ 'CURLOPT_TIMEOUT' => 5,
205
  ));
206
+
207
  // Debug point
208
+ self::debug('back to finished, response: '.preg_replace('/\s+/', ' ', str_replace("\n", ' ', print_r($response, true))));
209
+
210
  // End
211
  self::terminate();
212
  }
213
+
214
+ // Debug point
215
+ self::debug('end script');
216
+
217
  // End with post data
218
  self::terminate($postfields);
219
  }
229
  * Ends execution
230
  */
231
  private static function terminate($output = array()) {
232
+
233
  // Initialize
234
  $dump = '';
235
+
236
+ // Check array output
237
  if (!empty($output) && is_array($output)) {
238
+
239
  // JSON response
240
  @header('Content-Type: application/json');
241
+
242
  // Dump data
243
  $dump = self::json_encode(array(
244
  'status' => 'ok',
252
  @header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
253
  @header('Cache-Control: post-check=0, pre-check=0', false);
254
  @header('Pragma: no-cache');
255
+
256
  // Avoid indexation
257
  @header('X-Robots-Tag: noindex');
258
+
259
  // Debug point
260
  self::debug('script terminate');
261
+
262
  // End
263
  die($dump);
264
  }
269
  * A driver or wrapper for JSON encode
270
  */
271
  private static function json_encode($string) {
272
+
273
  // Check native function
274
  if (function_exists('json_encode')) {
275
  return @json_encode($string);
276
+
277
  // Other
278
  } else {
279
+
280
  // Globals
281
  global $wp_json;
282
+
283
  // Check current instance
284
  if (empty($wp_json) || !($wp_json instanceof Services_JSON)) {
285
+
286
  // Include file
287
  @require_once(dirname(__FILE__).'/class-json.php');
288
+
289
  // Create new object
290
+ if (class_exists('Services_JSON')) {
291
  $wp_json = new Services_JSON();
292
+ }
293
  }
294
+
295
  // Check object
296
  return (!empty($wp_json) && $wp_json instanceof Services_JSON)? $wp_json->encodeUnsafe($string) : false;
297
  }
299
 
300
 
301
 
 
 
 
 
 
302
  /**
303
  * Debug output
304
  */
305
  private static function debug($message) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
 
307
+ // Dependencies
308
+ static $started;
309
+ if (!isset($started)) {
310
+ $started = true;
311
+ require_once dirname(dirname(__FILE__)).'/debug.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  }
313
+
314
+ // Debug function call
315
+ wplnst_debug($message, 'HTTP');
316
  }
317
 
318
 
330
  * Response callback function
331
  */
332
  function wplnst_http_read_stream($ch, $line) {
333
+
334
  // Globals
335
  global $wplnst_http_response, $max_download, $max_download_done, $only_headers, $only_headers_done;
336
+
337
  // Current lengths
338
  $line_length = strlen($line);
339
  $total_length = strlen($wplnst_http_response);
340
+
341
  // Check overflow
342
  if (($total_length + $line_length) > $max_download) {
343
+
344
  // Check available size
345
  $available = $max_download - $total_length;
346
+ if ($available > 0) {
347
  $wplnst_http_response .= substr($line, 0, $available);
348
+ }
349
+
350
  // Max download achieved
351
  $max_download_done = true;
352
+
353
  // End
354
  return 0;
355
  }
356
+
357
  // Add new chunk
358
  $wplnst_http_response .= $line;
359
+
360
  // Check only headers
361
  if ($only_headers && false !== strpos($wplnst_http_response, "\r\n\r\n")) {
362
+
363
  // Headers achieved
364
  $only_headers_done = true;
365
+
366
  // End
367
  return 0;
368
  }
369
+
370
  // Done
371
  return strlen($line);
372
  }
core/scans.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Scans class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Scans {
10
 
@@ -19,60 +19,65 @@ class WPLNST_Core_Scans {
19
  * Retrieve existing scans
20
  */
21
  public function get_scans($args) {
22
-
23
  // Globals
24
  global $wpdb;
25
-
26
  // Prepare args
27
  $args = array_merge(array(
28
  'setup_rows' => true,
29
  'setup_names' => false,
30
  'no_cache' => false,
31
  ), $args);
32
-
33
  // Set vars
34
  extract($args);
35
-
36
  // Params
37
  $where = ' WHERE 1 = 1';
38
  $limit_rows = false;
39
-
40
  // Check scan id
41
- if (!empty($scan_id))
42
  $where .= ' AND scan_id = '.((int) $scan_id);
43
-
 
44
  // Check limit
45
  if (isset($limit)) {
46
  $check = array_map('intval', array_map('trim', explode(',', $limit)));
47
  if (1 == count($check)) {
48
- if ($check[0] > 0)
49
  $limit_rows = $check[0];
 
50
  } elseif (2 == count($check)) {
51
- if ($check[0] > 0 || $check[1] > 0)
52
  $limit_rows = $check[0].', '.$check[1];
 
53
  }
54
  }
55
-
56
  // Check single row
57
  if (1 === $limit_rows) {
58
-
59
  // Perform query
60
  $sql = 'SELECT'.(empty($no_cache)? '' : ' SQL_NO_CACHE').' * FROM '.$wpdb->prefix.'wplnst_scans'.$where.(empty($order_by)? '' : ' ORDER BY '.$order_by).' LIMIT 1';
61
  $results = (object) array('rows' => $wpdb->get_results($sql));
62
-
63
  // Multiple rows
64
  } else {
65
-
66
  // Check page
67
  $paged = empty($paged)? 1 : (int) $paged;
68
- if (empty($paged))
69
  $paged = 1;
70
-
 
71
  // Check elements per page
72
  $per_page = isset($per_page)? (int) $per_page : (int) get_user_option('wplnst_scans_per_page');
73
- if (empty($per_page))
74
  $per_page = WPLNST_Core_Types::scans_per_page;
75
-
 
76
  // Execute query
77
  $results = $this->pagination(array(
78
  'paged' => $paged,
@@ -84,17 +89,19 @@ class WPLNST_Core_Scans {
84
  'no_cache' => false,
85
  ));
86
  }
87
-
88
  // Check setup
89
- if (!$setup_rows || empty($results->rows))
90
  return $results;
91
-
 
92
  // Prepare rows
93
  $rows = array();
94
- foreach ($results->rows as $row)
95
  $rows[] = $this->setup_row_scan($row, $setup_names);
 
96
  $results->rows = $rows;
97
-
98
  // Done
99
  return $results;
100
  }
@@ -105,10 +112,10 @@ class WPLNST_Core_Scans {
105
  * Return scan by its id
106
  */
107
  public function get_scan_by_id($scan_id, $setup_names = false, $no_cache = false) {
108
-
109
  // Retrieve scans list
110
  $scans = $this->get_scans(array('scan_id' => $scan_id, 'setup_rows' => true, 'setup_names' => $setup_names, 'no_cache' => $no_cache, 'limit' => 1));
111
-
112
  // Count elements, return first or false
113
  return (!empty($scans->rows) && is_array($scans->rows) && 1 == count($scans->rows))? $scans->rows[0] : false;
114
  }
@@ -119,59 +126,66 @@ class WPLNST_Core_Scans {
119
  * Setup a scan database row
120
  */
121
  public function setup_row_scan($row, $names = false) {
122
-
123
  // Cache post types
124
  static $post_types;
125
- if (!isset($post_types))
126
  $post_types = WPLNST_Core_Types::get_post_types();
127
-
 
128
  // Cache post types keys
129
  static $post_types_keys;
130
- if (!isset($post_types_keys))
131
  $post_types_keys = array_keys($post_types);
132
-
 
133
  // Cache post status
134
  static $post_status_keys;
135
- if (!isset($post_status_keys))
136
  $post_status_keys = array_keys(WPLNST_Core_Types::get_post_status());
137
-
 
138
  // Cache status level
139
  static $status_levels;
140
- if (!isset($status_levels))
141
  $status_levels = WPLNST_Core_Types::get_status_levels();
142
-
 
143
  // Cache status levels keys
144
  static $status_levels_keys;
145
- if (!isset($status_levels_keys))
146
  $status_levels_keys = array_keys($status_levels);
147
-
 
148
  // Cache status codes
149
  static $status_codes_raw;
150
- if (!isset($status_codes_raw))
151
  $status_codes_raw = WPLNST_Core_Types::get_status_codes_raw();
152
-
 
153
  // Cache status codes keys
154
  static $status_codes_keys;
155
- if (!isset($status_codes_keys))
156
  $status_codes_keys = array_keys($status_codes_raw);
157
-
 
158
  // Scan object
159
  $scan = new stdClass;
160
  $scan->row = $row;
161
-
162
-
163
  /* scan values */
164
-
165
  // Cast fields
166
  $scan->id = (int) $row->scan_id;
167
  $scan->name = $row->name;
168
  $scan->status = $row->status;
169
  $scan->ready = (1 == (int) $row->ready);
170
  $scan->hash = $row->hash;
171
-
172
  // Decode config json field
173
  $config = @json_decode($row->config, true);
174
-
175
  // General tab
176
  $scan->destination_type = WPLNST_Core_Types::check_array_value($config, 'destination_type', array_keys(WPLNST_Core_Types::get_destination_types()), 'all');
177
  $scan->time_scope = WPLNST_Core_Types::check_array_value($config, 'time_scope', array_keys(WPLNST_Core_Types::get_time_scopes()), 'anytime');
@@ -182,7 +196,7 @@ class WPLNST_Core_Scans {
182
  $scan->notify_default = WPLNST_Core_Types::check_array_value($config, 'notify_default', true);
183
  $scan->notify_address = WPLNST_Core_Types::check_array_value($config, 'notify_address', true);
184
  $scan->notify_address_email = WPLNST_Core_Types::get_array_value($config, 'notify_address_email', '');
185
-
186
  // Content options tab
187
  $scan->post_types = (function_exists('did_action') && did_action('init'))? WPLNST_Core_Types::check_array_value($config, 'post_types', $post_types_keys, array()) : ((empty($config['post_types']) || !is_array($config['post_types']))? array() : $config['post_types']);
188
  $scan->post_status = WPLNST_Core_Types::check_array_value($config, 'post_status', $post_status_keys, array());
@@ -190,11 +204,11 @@ class WPLNST_Core_Scans {
190
  $scan->comment_types = WPLNST_Core_Types::check_array_value($config, 'comment_types', array_keys(WPLNST_Core_Types::get_comment_types()), array());
191
  $scan->check_comments = (!empty($scan->comment_types) && is_array($scan->comment_types));
192
  $scan->check_blogroll = WPLNST_Core_Types::check_array_value($config, 'blogroll', true);
193
-
194
  // Links status tab
195
  $scan->status_levels = WPLNST_Core_Types::check_array_value($config, 'status_levels', $status_levels_keys, array());
196
  $scan->status_codes = WPLNST_Core_Types::check_array_value($config, 'status_codes', array_keys(WPLNST_Core_Types::get_status_codes_raw()), array());
197
-
198
  // Filters
199
  $scan->custom_fields = WPLNST_Core_Types::check_array_json($config, 'custom_fields');
200
  $scan->anchor_filters = WPLNST_Core_Types::check_array_json($config, 'anchor_filters');
@@ -202,33 +216,34 @@ class WPLNST_Core_Scans {
202
  $scan->exclude_urls = WPLNST_Core_Types::check_array_json($config, 'exclude_urls');
203
  $scan->html_attributes = WPLNST_Core_Types::check_array_json($config, 'html_attributes');
204
  $scan->filtered_query = WPLNST_Core_Types::check_array_value($config, 'filtered_query', true);
205
-
206
-
207
  /* scan config values names */
208
-
209
  if ($names) {
210
-
211
  // Destination and Time scope
212
  $scan->destination_type_name = WPLNST_Core_Types::get_destination_type_name($scan->destination_type, 'all');
213
  $scan->time_scope_name = WPLNST_Core_Types::get_time_scope_name($scan->time_scope, 'anytime');
214
-
215
  // Links types
216
  $scan->link_types_names = WPLNST_Core_Types::get_link_types_names($scan->link_types);
217
-
218
  // Crawl order
219
  $scan->crawl_order_name = WPLNST_Core_Types::get_crawl_order_name($scan->crawl_order, 'desc');
220
-
221
  // Post types and status
222
  $scan->post_types_names = WPLNST_Core_Types::get_field_values_names($post_types, $scan->post_types);
223
  $scan->post_status_names = empty($scan->post_status)? array() : array_map('ucfirst', $scan->post_status);
224
-
225
  // A strict mode of post types names
226
  $scan->post_types_names_strict = array();
227
  foreach ($scan->post_types as $post_type_value) {
228
- if (isset($post_types[$post_type_value]))
229
  $scan->post_types_names_strict[] = esc_html($post_types[$post_type_value]).' (<code>'.esc_html($post_type_value).'</code>)';
 
230
  }
231
-
232
  // Comment types
233
  if ($scan->check_comments) {
234
  $scan->comment_types_names = WPLNST_Core_Types::get_comment_types_names($scan->comment_types);
@@ -238,61 +253,66 @@ class WPLNST_Core_Scans {
238
  $scan->post_types_names[] = sprintf(__('%s and %s comments', 'wplnst'), $scan->comment_types_names[0], lcfirst($scan->comment_types_names[1]));
239
  }
240
  }
241
-
242
  // Check blogroll type
243
- if ($scan->check_blogroll)
244
  $scan->post_types_names[] = __('Blogroll', 'wplnst');
245
-
 
246
  // Links status combined
247
  $scan->links_status_names = WPLNST_Core_Types::get_links_status_names_combined($scan->status_levels, $scan->status_codes);
248
-
249
  // Links status levels
250
  $scan->status_levels_names = array();
251
  foreach ($scan->status_levels as $status_level) {
252
- if (isset($status_levels[$status_level]))
253
  $scan->status_levels_names[] = $status_level.'00s ' .$status_levels[$status_level];
 
254
  }
255
-
256
  // Links status codes
257
  $scan->status_codes_names = array();
258
  foreach ($scan->status_codes as $status_code) {
259
- if (isset($status_codes_raw[$status_code]))
260
  $scan->status_codes_names[] = $status_code.' ' .$status_codes_raw[$status_code];
 
261
  }
262
  }
263
-
264
-
265
  /* Prepare trace values */
266
-
267
  // Decode trace json field
268
  $trace = @json_decode($row->trace, true);
269
- if (empty($trace) || !is_array($trace))
270
  $trace = array();
 
271
  $scan->trace = $trace;
272
-
273
-
274
  /* Prepare scan summary */
275
-
276
  $summary = @json_decode($row->summary, true);
277
- if (empty($summary) || !is_array($summary))
278
  $summary = array();
 
279
  $scan->summary = $summary;
280
-
281
-
282
  /* Prepare threads values */
283
-
284
  // Decode threads json field
285
  $threads = @json_decode($row->threads, true);
286
-
287
  // Create new object
288
  $scan->threads = new stdClass;
289
-
290
  // Assign object properties
291
  $scan->threads->current = (empty($threads) || !is_array($threads))? array() : $threads;
292
  $scan->threads->max = (int) $row->max_threads;
293
  $scan->threads->connect_timeout = (int) $row->connect_timeout;
294
  $scan->threads->request_timeout = (int) $row->request_timeout;
295
-
296
  // Done
297
  return $scan;
298
  }
@@ -303,22 +323,22 @@ class WPLNST_Core_Scans {
303
  * Remove existing scan data
304
  */
305
  public function delete_scan($scan_id) {
306
-
307
  // Globals
308
  global $wpdb;
309
-
310
  // Remove from main scans table
311
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
312
-
313
  // Remove from status table
314
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_status WHERE scan_id = %d', $scan_id));
315
-
316
  // Remove from locations table
317
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE scan_id = %d', $scan_id));
318
-
319
  // Remove from locations attributes table
320
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_locations_att WHERE scan_id = %d', $scan_id));
321
-
322
  // Remove from objects table
323
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = %d', $scan_id));
324
  }
@@ -329,10 +349,10 @@ class WPLNST_Core_Scans {
329
  * Number of running scans
330
  */
331
  public function get_scans_play_count() {
332
-
333
  // Globals
334
  global $wpdb;
335
-
336
  // Perform query
337
  return (int) $wpdb->get_var('SELECT SQL_NO_CACHE COUNT(*) FROM '.$wpdb->prefix.'wplnst_scans WHERE status = "play"');
338
  }
@@ -352,36 +372,40 @@ class WPLNST_Core_Scans {
352
  * Check if is ready to start a crawl
353
  */
354
  public static function is_scan_ready($scan) {
355
-
356
  // Initialize
357
  $result = array();
358
  $empty_post_types = false;
359
-
360
  // Check link types
361
- if (empty($scan->link_types) || !is_array($scan->link_types))
362
  $result['link_types'] = __('There is not any <strong>link type</strong> selected, you need to select one or more.', 'wplnst');
363
-
 
364
  // Check post types
365
- if (empty($scan->post_types) || !is_array($scan->post_types))
366
  $empty_post_types = true;
367
-
 
368
  // Check post status
369
  if (empty($scan->post_status) || !is_array($scan->post_status)) {
370
- if (!$empty_post_types)
371
  $result['post_status'] = __('Need to select any <strong>post status</strong> value for the selected post types.', 'wplnst');
 
372
  }
373
-
374
  // Check comments and blogroll
375
  if (!$scan->check_comments && !$scan->check_blogroll) {
376
  if ($empty_post_types) {
377
  $result['post_types'] = __('There is not any kind of <strong>post type</strong>, <strong>comments</strong> or <strong>blogroll</strong> selected.', 'wplnst');
378
  }
379
  }
380
-
381
  // Check status levels and status codes
382
- if ((empty($scan->status_levels) || !is_array($scan->status_levels)) && (empty($scan->status_codes) || !is_array($scan->status_codes)))
383
  $result['link_status'] = __('Missing selection of any <strong>links status</strong> level or status code.', 'wplnst');
384
-
 
385
  // Done
386
  return empty($result)? true : $result;
387
  }
@@ -392,10 +416,10 @@ class WPLNST_Core_Scans {
392
  * Update scan ready status
393
  */
394
  public function update_scan_ready($scan_id, $ready) {
395
-
396
  // Globals
397
  global $wpdb;
398
-
399
  // Perform query
400
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('ready' => $ready? 1 : 0), array('scan_id' => $scan_id));
401
  }
@@ -408,7 +432,7 @@ class WPLNST_Core_Scans {
408
  public function remove_stopped_time($scan_id) {
409
  // Globals
410
  global $wpdb;
411
-
412
  // Perform query
413
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('stopped_at' => '0000-00-00 00:00:00'), array('scan_id' => $scan_id));
414
  }
@@ -419,7 +443,7 @@ class WPLNST_Core_Scans {
419
  * Obtains fresh scan trace data
420
  */
421
  public function get_scan_trace($scan_id, $field = false) {
422
-
423
  // Globals
424
  global $wpdb;
425
 
@@ -427,7 +451,7 @@ class WPLNST_Core_Scans {
427
  $trace = $wpdb->get_var($wpdb->prepare('SELECT SQL_NO_CACHE trace FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
428
  $trace = @json_decode($trace, true);
429
  $trace = (empty($trace) || !is_array($trace))? array() : $trace;
430
-
431
  // Check field or all values
432
  return (false !== $field)? (isset($trace[$field])? $trace[$field] : false) : $trace;
433
  }
@@ -438,13 +462,13 @@ class WPLNST_Core_Scans {
438
  * Update scan trace values
439
  */
440
  public function update_scan_trace($scan_id, $values) {
441
-
442
  // Globals
443
  global $wpdb;
444
-
445
  // Merge trace values
446
  $trace = array_merge($this->get_scan_trace($scan_id), $values);
447
-
448
  // Update trace values
449
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('trace' => @json_encode($trace)), array('scan_id' => $scan_id));
450
  }
@@ -455,14 +479,14 @@ class WPLNST_Core_Scans {
455
  * Retrieve scan summary
456
  */
457
  public function get_scan_summary($scan_id) {
458
-
459
  // Globals
460
  global $wpdb;
461
-
462
  // Retrieve fresh summary data
463
  $summary = $wpdb->get_var($wpdb->prepare('SELECT SQL_NO_CACHE summary FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
464
  $summary = @json_decode($summary, true);
465
-
466
  // Check data
467
  return (empty($summary) || !is_array($summary))? array() : $summary;
468
  }
@@ -473,28 +497,30 @@ class WPLNST_Core_Scans {
473
  * Remove scan summary data by prefixed keys
474
  */
475
  public function remove_scan_summary_prefixed($scan_id, $prefixes) {
476
-
477
  // Globals
478
  global $wpdb;
479
-
480
  // Check value
481
- if (empty($prefixes))
482
  return;
483
-
 
484
  // Check array
485
- if (!is_array($prefixes))
486
  $prefixes = array($prefixes);
487
-
 
488
  // Current data
489
  $summary = $this->get_scan_summary($scan_id);
490
  if (!empty($summary)) {
491
-
492
  // Initialize
493
  $summary2 = array();
494
 
495
  // Enum summary data
496
  foreach ($summary as $key => $value) {
497
-
498
  // Check prefixes
499
  $match = false;
500
  foreach ($prefixes as $prefix) {
@@ -503,18 +529,20 @@ class WPLNST_Core_Scans {
503
  break;
504
  }
505
  }
506
-
507
  // Removed
508
- if ($match)
509
  continue;
510
-
 
511
  // Copy data
512
  $summary2[$key] = $value;
513
  }
514
-
515
  // Check summary update
516
- if (count($summary) != count($summary2))
517
  $this->update_scan_summary($scan_id, $summary2, false);
 
518
  }
519
  }
520
 
@@ -524,16 +552,16 @@ class WPLNST_Core_Scans {
524
  * Update scan summary data
525
  */
526
  public function update_scan_summary($scan_id, $values, $merge = true) {
527
-
528
  // Globals
529
  global $wpdb;
530
-
531
  // Check previous summary
532
  $summary = $this->get_scan_summary($scan_id);
533
-
534
  // Merge data
535
  $summary = (empty($summary) || !$merge)? $values : array_merge($summary, $values);
536
-
537
  // Update data
538
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('summary' => @json_encode($summary)), array('scan_id' => $scan_id));
539
  }
@@ -544,90 +572,95 @@ class WPLNST_Core_Scans {
544
  * Update URL info for summary
545
  */
546
  public function set_scan_summary_status_codes($scan_id, $status_levels, $status_codes, $final = false) {
547
-
548
  // Globals
549
  global $wpdb;
550
-
551
  // Not the last
552
  if (!$final) {
553
-
554
  // Check timestamp
555
  $timestamp = $this->get_scan_trace($scan_id, 'summary_status_codes');
556
- if (false !== $timestamp && (time() - $timestamp) < wplnst_get_nsetting('summary_status'))
557
  return;
558
-
 
559
  // Update timestamp
560
  $this->update_scan_trace($scan_id, array('summary_status_codes' => time()));
561
  }
562
-
563
  // Check levels
564
- if (!empty($status_levels) && is_array($status_levels))
565
  $where_levels = 's.status_level IN ("0", "'.implode('", "', array_map('esc_sql', $status_levels)).'")';
566
-
 
567
  // Check codes
568
- if (!empty($status_codes) && is_array($status_codes))
569
  $where_codes = 's.status_code IN ("0", "'.implode('", "', array_map('esc_sql', $status_codes)).'")';
570
-
 
571
  // Compose combined
572
  if (isset($where_levels) && isset($where_codes)) {
573
  $where = ' AND ('.$where_levels.' OR '.$where_codes.')';
574
-
575
  // Only levels
576
  } elseif (isset($where_levels)) {
577
  $where = ' AND '.$where_levels;
578
-
579
  // Only codes
580
  } elseif (isset($where_codes)) {
581
  $where = ' AND '.$where_codes;
582
-
583
  // Error
584
  } else {
585
  return;
586
  }
587
-
588
  // Initialize
589
  $total = 0;
590
  $codes = array();
591
  $levels = array();
592
-
593
  // Retrieve totals of codes for not ignored locations
594
  $results = $wpdb->get_results($wpdb->prepare('SELECT s.status_code, COUNT(*) total FROM '.$wpdb->prefix.'wplnst_urls_status s RIGHT JOIN '.$wpdb->prefix.'wplnst_urls_locations l ON s.url_id = l.url_id AND s.scan_id = l.scan_id WHERE s.scan_id = %d '.$where.' AND s.phase = "end" AND l.ignored = 0 GROUP BY status_code', $scan_id));
595
-
596
  // Cast data to array
597
  if (!empty($results) && is_array($results)) {
598
-
599
  // Enum code results
600
  foreach ($results as $result) {
601
-
602
  // Sum all codes
603
  $total += (int) $result->total;
604
-
605
  // Total for this code
606
  $codes[$result->status_code] = (int) $result->total;
607
-
608
  // Total for this level
609
  $level_key = mb_substr($result->status_code, 0, 1);
610
  $levels[$level_key] = isset($levels[$level_key])? $levels[$level_key] + $codes[$result->status_code] : $codes[$result->status_code];
611
  }
612
  }
613
-
614
  // Prepare to summary
615
  $summary_keys = array();
616
-
617
  // Prefix code keys
618
- foreach ($codes as $key => $value)
619
  $summary_keys['status_code_'.$key] = $value;
620
-
 
621
  // Prefix level keys
622
- foreach ($levels as $key => $value)
623
  $summary_keys['status_level_'.$key] = $value;
624
-
 
625
  // Total results
626
  $summary_keys['status_total'] = $total;
627
-
628
  // Remove old summary status values
629
  $this->remove_scan_summary_prefixed($scan_id, array('status_code_', 'status_level_'));
630
-
631
  // Update summary data
632
  $this->update_scan_summary($scan_id, $summary_keys);
633
  }
@@ -638,34 +671,36 @@ class WPLNST_Core_Scans {
638
  * Update URL info for summary
639
  */
640
  public function set_scan_summary_urls_phases($scan_id, $final = false) {
641
-
642
  // Globals
643
  global $wpdb;
644
-
645
  // Not the last
646
  if (!$final) {
647
-
648
  // Check timestamp
649
  $timestamp = $this->get_scan_trace($scan_id, 'summary_url_phases');
650
- if (false !== $timestamp && (time() - $timestamp) < wplnst_get_nsetting('summary_phases'))
651
  return;
652
-
 
653
  // Update timestamp
654
  $this->update_scan_trace($scan_id, array('summary_url_phases' => time()));
655
  }
656
-
657
  // Initialize
658
  $phases = array();
659
-
660
  // Retrieve totals of phases
661
  $results = $wpdb->get_results($wpdb->prepare('SELECT phase, COUNT(*) total FROM '.$wpdb->prefix.'wplnst_urls_status WHERE scan_id = %d GROUP BY phase', $scan_id));
662
-
663
  // Cast data to array
664
  if (!empty($results) && is_array($results)) {
665
- foreach ($results as $result)
666
  $phases[$result->phase] = (int) $result->total;
 
667
  }
668
-
669
  // Merge default values
670
  $phases = array_merge(array(
671
  'wait' => 0,
@@ -675,18 +710,19 @@ class WPLNST_Core_Scans {
675
  'discard' => 0,
676
  'failed' => 0
677
  ), $phases);
678
-
679
  // Sum redir to wait
680
  $phases['wait'] += $phases['redir'];
681
-
682
  // New values combined
683
  $phases['processed'] = $phases['end'] + $phases['discard'] + $phases['failed'];
684
-
685
  // Prefix keys
686
  $summary_phases = array();
687
- foreach ($phases as $key => $value)
688
  $summary_phases['urls_phase_'.$key] = $value;
689
-
 
690
  // Update summary data
691
  $this->update_scan_summary($scan_id, $summary_phases);
692
  }
@@ -695,27 +731,28 @@ class WPLNST_Core_Scans {
695
 
696
  /**
697
  * Obtains the total match objects and update summary
698
- */
699
  public function set_scan_summary_objects_match($scan_id, $object_type, $final = false) {
700
-
701
  // Globals
702
  global $wpdb;
703
-
704
  // Not the last
705
  if (!$final) {
706
-
707
  // Check timestamp
708
  $timestamp = $this->get_scan_trace($scan_id, 'summary_objects_match');
709
- if (false !== $timestamp && (time() - $timestamp) < wplnst_get_nsetting('summary_objects'))
710
  return;
711
-
 
712
  // Update timestamp
713
  $this->update_scan_trace($scan_id, array('summary_objects_match' => time()));
714
  }
715
-
716
  // Perform query
717
  $objects_match = (int) $wpdb->get_var($wpdb->prepare('SELECT COUNT(DISTINCT object_id) FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE scan_id = %d AND object_type = %s', $scan_id, $object_type));
718
-
719
  // Update summary data
720
  $this->update_scan_summary($scan_id, array('objects_match_'.$object_type => $objects_match));
721
  }
@@ -727,23 +764,23 @@ class WPLNST_Core_Scans {
727
  * This works at the end of an scan crawling process
728
  */
729
  public function set_scan_final_threads_options($scan_id, $args) {
730
-
731
  // Globals
732
  global $wpdb;
733
-
734
  $args = array_merge(array(
735
  'max_threads' => 0,
736
  'connect_timeout' => 0,
737
  'request_timeout' => 0,
738
  ), $args);
739
-
740
  // Prepare update
741
  $update = array(
742
  'max_threads' => wplnst_get_nsetting('max_threads', $args['max_threads']),
743
  'connect_timeout' => wplnst_get_nsetting('connect_timeout', $args['connect_timeout']),
744
  'request_timeout' => wplnst_get_nsetting('request_timeout', $args['request_timeout']),
745
  );
746
-
747
  // Update
748
  return $wpdb->update($wpdb->prefix.'wplnst_scans', $update, array('scan_id' => $scan_id));
749
  }
@@ -759,10 +796,10 @@ class WPLNST_Core_Scans {
759
  * Obtains fresh scan status data
760
  */
761
  public function get_scan_status($scan_id) {
762
-
763
  // Globals
764
  global $wpdb;
765
-
766
  // Return status
767
  return $wpdb->get_var($wpdb->prepare('SELECT SQL_NO_CACHE status FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
768
  }
@@ -773,10 +810,10 @@ class WPLNST_Core_Scans {
773
  * Stop any playing scan
774
  */
775
  public function stop_playing_scans() {
776
-
777
  // Globals
778
  global $wpdb;
779
-
780
  // Perform query
781
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'stop'), array('status' => 'play'));
782
  }
@@ -787,10 +824,10 @@ class WPLNST_Core_Scans {
787
  * Queue a given scan
788
  */
789
  public function queue_scan($scan_id) {
790
-
791
  // Globals
792
  global $wpdb;
793
-
794
  // Perform query
795
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'queued', 'enqueued_at' => current_time('mysql', true)), array('scan_id' => $scan_id));
796
  }
@@ -801,10 +838,10 @@ class WPLNST_Core_Scans {
801
  * Unqueue scan, cast to wait
802
  */
803
  public function unqueue_scan($scan_id) {
804
-
805
  // Globals
806
  global $wpdb;
807
-
808
  // Perform query
809
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'wait'), array('scan_id' => $scan_id));
810
  }
@@ -815,13 +852,13 @@ class WPLNST_Core_Scans {
815
  * Play a given scan
816
  */
817
  public function play_scan($scan_id, $continued = false) {
818
-
819
  // Globals
820
  global $wpdb;
821
-
822
  // Decide field
823
  $time_field = $continued? 'continued_at' : 'started_at';
824
-
825
  // Perform query
826
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'play', $time_field => current_time('mysql', true)), array('scan_id' => $scan_id));
827
  }
@@ -832,10 +869,10 @@ class WPLNST_Core_Scans {
832
  * Stop a given scan
833
  */
834
  public function stop_scan($scan_id) {
835
-
836
  // Globals
837
  global $wpdb;
838
-
839
  // Perform query
840
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'stop', 'stopped_at' => current_time('mysql', true)), array('scan_id' => $scan_id));
841
  }
@@ -846,10 +883,10 @@ class WPLNST_Core_Scans {
846
  * Terminated scan
847
  */
848
  public function end_scan($scan_id) {
849
-
850
  // Globals
851
  global $wpdb;
852
-
853
  // Perform query
854
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'end', 'finished_at' => current_time('mysql', true)), array('scan_id' => $scan_id));
855
  }
@@ -865,42 +902,45 @@ class WPLNST_Core_Scans {
865
  * Replacement function of WP API because we need meta_id
866
  */
867
  public function get_post_metas($post_id) {
868
-
869
  // Globals
870
  global $wpdb;
871
-
872
  // Check keys input
873
- if (!empty($keys) && !is_array($keys))
874
  $keys = array($keys);
875
-
 
876
  // Retrieve metas
877
  $rows = $wpdb->get_results($wpdb->prepare('SELECT * FROM '.$wpdb->postmeta.' WHERE post_id = %d ORDER BY meta_id ASC', $post_id));
878
-
879
  // Check results
880
  if (!empty($rows) && is_array($rows)) {
881
-
882
  // Initialize
883
  $metas = array();
884
-
885
  // Enum rrows
886
  foreach ($rows as $row) {
887
-
888
  // Check meta key
889
- if (empty($row->meta_key))
890
  continue;
891
-
 
892
  // Check by name
893
- if (!isset($metas[$row->meta_key]))
894
  $metas[$row->meta_key] = array();
895
-
 
896
  // Add value
897
  $metas[$row->meta_key][$row->meta_id] = $row->meta_value;
898
  }
899
-
900
  // Done
901
  return $metas;
902
  }
903
-
904
  // Not found
905
  return false;
906
  }
@@ -911,10 +951,10 @@ class WPLNST_Core_Scans {
911
  * Register by identifiers before process the object
912
  */
913
  public function register_scan_object($scan_id, $object_id, $object_type, $object_date_gmt = "0000-00-00 00:00:00") {
914
-
915
  // Globals
916
  global $wpdb;
917
-
918
  // Insert attempt
919
  return (1 == (int) $wpdb->query($wpdb->prepare('INSERT IGNORE INTO '.$wpdb->prefix.'wplnst_scans_objects SET scan_id = %d, object_id = %d, object_type = %s, object_date_gmt = %s', $scan_id, $object_id, $object_type, $object_date_gmt)));
920
  }
@@ -925,10 +965,10 @@ class WPLNST_Core_Scans {
925
  * Check if exists an scan object
926
  */
927
  public function scan_object_exists($scan_id, $object_id, $object_type) {
928
-
929
  // Globals
930
  global $wpdb;
931
-
932
  // Number of occurrences
933
  return (1 == (int) $wpdb->get_var($wpdb->prepare('SELECT SQL_NO_CACHE COUNT(*) FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = %d AND object_id = %d AND object_type = %s', $scan_id, $object_id, $object_type)));
934
  }
@@ -939,10 +979,10 @@ class WPLNST_Core_Scans {
939
  * Retrieve object identifiers based on type and same date
940
  */
941
  public function get_scan_objects_ids_by_date($scan_id, $object_type, $object_date_gmt) {
942
-
943
  // Globals
944
  global $wpdb;
945
-
946
  // Number of occurrences
947
  return $wpdb->get_col($wpdb->prepare('SELECT SQL_NO_CACHE object_id FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = %d AND object_type = %s AND object_date_gmt = %s', $scan_id, $object_type, $object_date_gmt));
948
  }
@@ -953,10 +993,10 @@ class WPLNST_Core_Scans {
953
  * Return the amount of registered objects
954
  */
955
  public function get_scan_objects_count($scan_id, $object_type) {
956
-
957
  // Globals
958
  global $wpdb;
959
-
960
  // Insert attempt
961
  return (int) $wpdb->get_var($wpdb->prepare('SELECT COUNT(*) FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = %d AND object_type = %s', $scan_id, $object_type));
962
  }
@@ -967,10 +1007,10 @@ class WPLNST_Core_Scans {
967
  * Remove all scan registered objects
968
  */
969
  public function remove_scan_objects($scan_id) {
970
-
971
  // Globals
972
  global $wpdb;
973
-
974
  // Insert attempt
975
  return (int) $wpdb->get_var($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = %d', $scan_id));
976
  }
@@ -981,35 +1021,36 @@ class WPLNST_Core_Scans {
981
  * Retrieve scan URL data
982
  */
983
  public function get_scan_url($args) {
984
-
985
  // Globals
986
  global $wpdb;
987
-
988
  // Arguments
989
  extract($args);
990
-
991
  // Check by id
992
  if (isset($id)) {
993
-
994
  // Check identifier
995
  $id = (int) $id;
996
  if (!empty($id)) {
997
  $row = $wpdb->get_row($wpdb->prepare('SELECT '.(isset($no_cache)? 'SQL_NO_CACHE ' : '').'* FROM '.$wpdb->prefix.'wplnst_urls WHERE url_id = %d', $id));
998
  return empty($row)? false : $row;
999
  }
1000
-
1001
  // By URL string
1002
  } elseif (isset($url)) {
1003
-
1004
  // Retrieve URLs by hash
1005
  $rows = $wpdb->get_results($wpdb->prepare('SELECT '.(isset($no_cache)? 'SQL_NO_CACHE ' : '').'* FROM '.$wpdb->prefix.'wplnst_urls WHERE hash = %s ORDER BY url_id ASC', $this->get_url_hash($url)));
1006
- if (empty($rows) || !is_array($rows) || 1 != count($rows))
1007
  return false;
1008
-
 
1009
  // Done
1010
  return $rows[0];
1011
  }
1012
-
1013
  // Default
1014
  return false;
1015
  }
@@ -1020,26 +1061,28 @@ class WPLNST_Core_Scans {
1020
  * Creates a 64 bytes hash to avoid URLs collisions
1021
  */
1022
  public function get_url_hash($url) {
1023
-
1024
  // First part
1025
  $hash = md5($url);
1026
-
1027
  // Another version
1028
  $url2 = array();
1029
-
1030
  // Special chars
1031
  static $special;
1032
- if (!isset($special))
1033
  $special = array(";", "/", "?", ":", "@", "&", "=", "+", "$", ",", "-", "_", ".", "!", "~", "*", "'", "(", ")");
1034
-
 
1035
  // Enum URL chars
1036
  $length = mb_strlen($url);
1037
  for ($i = 0; $i < $length; $i++) {
1038
  $char = mb_substr($url, $i, 1);
1039
- if (!in_array($char, $special))
1040
  $url2[] = $char;
 
1041
  }
1042
-
1043
  // Return combined hash
1044
  return $hash.md5(implode('', array_reverse($url2)));
1045
  }
@@ -1050,7 +1093,7 @@ class WPLNST_Core_Scans {
1050
  * Retrieve next URL with next value
1051
  */
1052
  public function get_scan_url_waiting($scan_id) {
1053
-
1054
  // Retrieve by wait status
1055
  if (false !== ($rows = $this->get_scan_url_status(array(
1056
  'scan_id' => $scan_id,
@@ -1059,22 +1102,22 @@ class WPLNST_Core_Scans {
1059
  'no_cache' => true,
1060
  'limit_rows' => 1,
1061
  )))) {
1062
-
1063
  // Retrieve url
1064
  $url = $this->get_scan_url(array('id' => $rows[0]->url_id, 'no_cache' => true));
1065
  if (false !== $url) {
1066
-
1067
  // Check a redirection
1068
  if ('redir' == $rows[0]->phase) {
1069
  $url->url = $rows[0]->redirect_url;
1070
  $url->redirection = true;
1071
  }
1072
  }
1073
-
1074
  // Done
1075
  return $url;
1076
  }
1077
-
1078
  // Default
1079
  return false;
1080
  }
@@ -1085,33 +1128,34 @@ class WPLNST_Core_Scans {
1085
  * Add new URL scan
1086
  */
1087
  public function add_scan_url($link, $scan_id) {
1088
-
1089
  // Globals
1090
  global $wpdb;
1091
-
1092
  // Create hash
1093
  $hash = $this->get_url_hash($link['url']);
1094
-
1095
  // Prepare fields
1096
  $scheme = isset($link['scheme'])? mb_substr($link['scheme'], 0, 20) : '';
1097
  $host = isset($link['host'])? mb_substr($link['host'], 0, 255) : '';
1098
  $path = isset($link['path'])? mb_substr($link['path'], 0, 255) : '';
1099
  $query = isset($link['query'])? mb_substr($link['query'], 0, 255) : '';
1100
  $scope = isset($link['scope'])? $link['scope'] : '';
1101
-
1102
  // Add new scan status
1103
  $result = $wpdb->query($wpdb->prepare('INSERT IGNORE INTO '.$wpdb->prefix.'wplnst_urls SET url = %s, hash = %s, scheme = %s, host = %s, path = %s, query = %s, scope = %s, created_at = %s, last_scan_id = %d', $link['url'], $hash, $scheme, $host, $path, $query, $scope, current_time('mysql', true), $scan_id));
1104
  if (!empty($wpdb->insert_id)) {
1105
  return $wpdb->insert_id;
1106
-
1107
  // Collision?
1108
  } else {
1109
-
1110
  // Retrieve existing URL record
1111
  $rows = $wpdb->get_results($wpdb->prepare('SELECT url_id, url FROM '.$wpdb->prefix.'wplnst_urls WHERE hash = %s', $hash));
1112
- if (empty($rows) || !is_array($rows) || 1 != count($rows))
1113
  return false;
1114
-
 
1115
  // Return id only if URLs are the same
1116
  return ($rows[0]->url === $url)? $rows[0]->url_id : false;
1117
  }
@@ -1123,10 +1167,10 @@ class WPLNST_Core_Scans {
1123
  * Update URL scan data
1124
  */
1125
  public function update_scan_url($url_id, $update) {
1126
-
1127
  // Globals
1128
  global $wpdb;
1129
-
1130
  // Update play value
1131
  return $wpdb->update($wpdb->prefix.'wplnst_urls', $update, array('url_id' => $url_id));
1132
  }
@@ -1137,10 +1181,10 @@ class WPLNST_Core_Scans {
1137
  * Add location for scan url
1138
  */
1139
  public function add_scan_url_location($url_id, $scan_id, $link) {
1140
-
1141
  // Globals
1142
  global $wpdb;
1143
-
1144
  // Add new url
1145
  $wpdb->insert($wpdb->prefix.'wplnst_urls_locations', array(
1146
  'url_id' => $url_id,
@@ -1163,7 +1207,7 @@ class WPLNST_Core_Scans {
1163
  'relative' => $link['relative']? 1 : 0,
1164
  'nofollow' => $link['nofollow']? 1 : 0,
1165
  ));
1166
-
1167
  // Result
1168
  return empty($wpdb->insert_id)? false : $wpdb->insert_id;
1169
  }
@@ -1174,10 +1218,10 @@ class WPLNST_Core_Scans {
1174
  * Update location fields
1175
  */
1176
  public function update_scan_url_location($loc_id, $update) {
1177
-
1178
  // Globals
1179
  global $wpdb;
1180
-
1181
  // Update
1182
  return $wpdb->update($wpdb->prefix.'wplnst_urls_locations', $update, array('loc_id' => $loc_id));
1183
  }
@@ -1188,8 +1232,9 @@ class WPLNST_Core_Scans {
1188
  * Update several locations
1189
  */
1190
  public function update_scan_url_locations($loc_ids, $update) {
1191
- foreach ($loc_ids as $loc_id)
1192
  $this->update_scan_url_location($loc_id, $update);
 
1193
  }
1194
 
1195
 
@@ -1198,17 +1243,18 @@ class WPLNST_Core_Scans {
1198
  * Update posts fields
1199
  */
1200
  public function update_scan_post($post_id, $update, $clean_cache = true) {
1201
-
1202
  // Globals
1203
  global $wpdb;
1204
-
1205
  // Update
1206
  $result = $wpdb->update($wpdb->posts, $update, array('ID' => $post_id));
1207
-
1208
  // Check cache
1209
- if ($clean_cache)
1210
  clean_post_cache($post_id);
1211
-
 
1212
  // Done
1213
  return $result;
1214
  }
@@ -1219,17 +1265,18 @@ class WPLNST_Core_Scans {
1219
  * Update meta associated to post
1220
  */
1221
  public function update_scan_post_meta($post_id, $meta_id, $content, $clean_cache = true) {
1222
-
1223
  // Globals
1224
  global $wpdb;
1225
-
1226
  // Update
1227
  $result = $wpdb->update($wpdb->postmeta, array('meta_value' => $content), array('meta_id' => $meta_id));
1228
-
1229
  // Check cache
1230
- if ($clean_cache)
1231
  clean_post_cache($post_id);
1232
-
 
1233
  // Done
1234
  return $result;
1235
  }
@@ -1240,17 +1287,18 @@ class WPLNST_Core_Scans {
1240
  * Update comment fields
1241
  */
1242
  public function update_scan_comment($comment_id, $update, $clean_cache = true) {
1243
-
1244
  // Globals
1245
  global $wpdb;
1246
-
1247
  // Update
1248
  $result = $wpdb->update($wpdb->comments, $update, array('comment_ID' => $comment_id));
1249
-
1250
  // Check cache
1251
- if ($clean_cache)
1252
  clean_comment_cache($comment_id);
1253
-
 
1254
  // Done
1255
  return $result;
1256
  }
@@ -1261,17 +1309,18 @@ class WPLNST_Core_Scans {
1261
  * Update bookmark fields
1262
  */
1263
  public function update_scan_bookmark($link_id, $update, $clean_cache = true) {
1264
-
1265
  // Globals
1266
  global $wpdb;
1267
-
1268
  // Update
1269
  $result = $wpdb->update($wpdb->links, $update, array('link_id' => $link_id));
1270
-
1271
  // Check cache
1272
- if ($clean_cache)
1273
  clean_bookmark_cache($link_id);
1274
-
 
1275
  // Done
1276
  return $result;
1277
  }
@@ -1282,29 +1331,30 @@ class WPLNST_Core_Scans {
1282
  * Update total content for a given URL
1283
  */
1284
  public function set_scan_url_status_total_content($url_id, $scan_id) {
1285
-
1286
  // Globals
1287
  global $wpdb;
1288
-
1289
  // Initialize
1290
  $total = array();
1291
-
1292
  // Retrieve total rows by object type
1293
  $results = $wpdb->get_results($wpdb->prepare('SELECT object_type, COUNT(*) total FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE url_id = %d AND scan_id = %d GROUP BY object_type', $url_id, $scan_id));
1294
-
1295
  // Cast data to array
1296
  if (!empty($results) && is_array($results)) {
1297
- foreach ($results as $result)
1298
  $total[$result->object_type] = (int) $result->total;
 
1299
  }
1300
-
1301
  // Merge default values
1302
  $total = array_merge(array(
1303
  'posts' => 0,
1304
  'comments' => 0,
1305
  'blogroll' => 0,
1306
  ), $total);
1307
-
1308
  // Update scan URL status row
1309
  $this->update_scan_url_status($url_id, $scan_id, array('total_posts' => $total['posts'], 'total_comments' => $total['comments'], 'total_blogroll' => $total['blogroll']));
1310
  }
@@ -1315,50 +1365,57 @@ class WPLNST_Core_Scans {
1315
  * Retrieve URL status info
1316
  */
1317
  public function get_scan_url_status($args = array()) {
1318
-
1319
  // Globals
1320
  global $wpdb;
1321
-
1322
  // Check arguments
1323
- if (empty($args) || !is_array($args))
1324
  return false;
1325
-
 
1326
  // Extract parameters
1327
  extract($args);
1328
-
1329
  // Cast arguments
1330
  $url_id = isset($url_id)? (int) $url_id : 0;
1331
  $scan_id = isset($scan_id)? (int) $scan_id : 0;
1332
  $status = isset($status)? $status : false;
1333
  $phase = isset($phase)? $phase : false;
1334
-
1335
  // Check identifiers
1336
- if (empty($url_id) && empty($scan_id))
1337
  return false;
1338
-
 
1339
  // Force cache for an isolated record
1340
- if (!isset($no_cache) && !empty($url_id) && !empty($scan_id))
1341
  $no_cache = true;
1342
-
 
1343
  // Initialize
1344
  $where = '1 = 1';
1345
-
1346
  // Check URL id
1347
- if (!empty($url_id))
1348
  $where .= ' AND url_id = '.$url_id;
1349
-
 
1350
  // Check scan id
1351
- if (!empty($scan_id))
1352
  $where .= ' AND scan_id = '.$scan_id;
1353
-
 
1354
  // Check status
1355
- if (false !== $status)
1356
  $where .= ' AND status = "'.esc_sql($status).'"';
1357
-
 
1358
  // Check phase
1359
- if (false !== $phase)
1360
  $where .= ' AND phase'.(is_array($phase)? ' IN ("'.implode('", "', array_map('esc_sql', $phase)).'")' : ' = "'.esc_sql($phase).'"');
1361
-
 
1362
  // Order
1363
  $order_by = '';
1364
  if (isset($order)) {
@@ -1368,24 +1425,26 @@ class WPLNST_Core_Scans {
1368
  if (2 == count($order_item)) {
1369
  if (in_array($order_item[0], array('url_id', 'scan_id', 'status', 'created_at', 'started_at'))) {
1370
  $order_item[1] = strtoupper($order_item[1]);
1371
- if ('ASC' == $order_item[1] || 'DESC' == $order_item[1])
1372
  $order_by .= (empty($order_by)? ' ORDER BY ' : $order_by.', ').$order_item[0].' '.$order_item[1];
 
1373
  }
1374
  }
1375
  }
1376
  }
1377
-
1378
  // Limit
1379
  $limit = '';
1380
  if (isset($limit_rows)) {
1381
  $limit_rows = (int) $limit_rows;
1382
- if (!empty($limit_rows))
1383
  $limit = ' LIMIT '.(isset($limit_base)? (int) $limit_base.', ' : '').$limit_rows;
 
1384
  }
1385
-
1386
  // Perform query
1387
  $rows = $wpdb->get_results('SELECT '.(isset($no_cache)? 'SQL_NO_CACHE ' : '').'* FROM '.$wpdb->prefix.'wplnst_urls_status WHERE '.$where.$order_by.$limit);
1388
-
1389
  // Done
1390
  return (empty($rows) || !is_array($rows))? false : $rows;
1391
  }
@@ -1396,10 +1455,10 @@ class WPLNST_Core_Scans {
1396
  * New URL status record
1397
  */
1398
  public function new_scan_url_status($url_id, $scan_id, $insert) {
1399
-
1400
  // Globals
1401
  global $wpdb;
1402
-
1403
  // Add new scan status
1404
  return $wpdb->query($wpdb->prepare('INSERT IGNORE INTO '.$wpdb->prefix.'wplnst_urls_status SET url_id = %d, scan_id = %d, phase = %s, created_at = %s', $url_id, $scan_id, $phase, current_time('mysql', true)));
1405
  }
@@ -1410,10 +1469,10 @@ class WPLNST_Core_Scans {
1410
  * Insert new URL status record
1411
  */
1412
  public function add_scan_url_status($url_id, $scan_id, $phase) {
1413
-
1414
  // Globals
1415
  global $wpdb;
1416
-
1417
  // Add new scan status
1418
  return $wpdb->query($wpdb->prepare('INSERT IGNORE INTO '.$wpdb->prefix.'wplnst_urls_status SET url_id = %d, scan_id = %d, phase = %s, created_at = %s', $url_id, $scan_id, $phase, current_time('mysql', true)));
1419
  }
@@ -1424,10 +1483,10 @@ class WPLNST_Core_Scans {
1424
  * Update a URL status phase
1425
  */
1426
  public function update_scan_url_status($url_id, $scan_id, $update) {
1427
-
1428
  // Globals
1429
  global $wpdb;
1430
-
1431
  // Update play value
1432
  return $wpdb->update($wpdb->prefix.'wplnst_urls_status', $update, array('url_id' => $url_id, 'scan_id' => $scan_id));
1433
  }
@@ -1438,10 +1497,10 @@ class WPLNST_Core_Scans {
1438
  * Remove URL status record
1439
  */
1440
  public function remove_scan_url_status($url_id, $scan_id) {
1441
-
1442
  // Globals
1443
  global $wpdb;
1444
-
1445
  // Remove record
1446
  return $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_status WHERE url_id = %d AND scan_id = %d LIMIT 1', $url_id, $scan_id));
1447
  }
@@ -1452,13 +1511,13 @@ class WPLNST_Core_Scans {
1452
  * Remove discard URL status and locations
1453
  */
1454
  public function remove_scan_discard_urls($scan_id) {
1455
-
1456
  // Globals
1457
  global $wpdb;
1458
-
1459
  // Remove locations
1460
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE scan_id = %d AND url_id IN (SELECT url_id FROM '.$wpdb->prefix.'wplnst_urls_status WHERE scan_id = %d AND phase = "discard")', $scan_id, $scan_id));
1461
-
1462
  // Remove URL status
1463
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_status WHERE scan_id = %d AND phase = "discard"', $scan_id));
1464
  }
@@ -1474,10 +1533,10 @@ class WPLNST_Core_Scans {
1474
  * Retrieve URL request headers
1475
  */
1476
  public function get_scan_result_headers($scan_id, $url_id) {
1477
-
1478
  // Globals
1479
  global $wpdb;
1480
-
1481
  // Retrieve headers
1482
  return $wpdb->get_row($wpdb->prepare('SELECT headers, headers_request, request_at, total_time, total_bytes FROM '.$wpdb->prefix.'wplnst_urls_status WHERE url_id = %d AND scan_id = %d', $url_id, $scan_id));
1483
  }
@@ -1488,89 +1547,99 @@ class WPLNST_Core_Scans {
1488
  * Retrieve scan results
1489
  */
1490
  public function get_scan_results($args) {
1491
-
1492
  // Globals
1493
  global $wpdb;
1494
-
1495
  // Check arguments
1496
- if (empty($args) || !is_array($args))
1497
  return false;
1498
-
 
1499
  // Extract parameters
1500
  extract($args);
1501
-
1502
  // Check scan id
1503
  $scan_id = empty($scan_id)? 0 : (int) $scan_id;
1504
- if (empty($scan_id))
1505
  return false;
1506
-
 
1507
  // Check page
1508
  $paged = empty($paged)? 1 : (int) $paged;
1509
- if (empty($paged))
1510
  $paged = 1;
1511
-
 
1512
  // Check elements per page
1513
  $per_page = isset($per_page)? (int) $per_page : (int) get_user_option('wplnst_scan_results_per_page');
1514
- if (empty($per_page))
1515
  $per_page = WPLNST_Core_Types::scans_results_per_page;
1516
-
 
1517
  // Prepare fields
1518
  $fields = 'u.url_id, u.url, u.scheme, u.host, u.scope,';
1519
  $fields .= 's.status_level, s.status_code, s.curl_errno, s.phase, s.redirect_url, s.redirect_steps, s.redirect_url_id, s.redirect_url_status, s.redirect_curl_errno, s.total_posts, s.total_comments, s.total_blogroll, s.total_time, s.total_bytes, s.rechecked, s.requests,';
1520
  $fields .= 'l.loc_id, l.link_type, l.object_id, l.object_type, l.object_field, l.detected_at, l.anchor, l.raw_url, l.fragment, l.spaced, l.malformed, l.absolute, l.protorel, l.relative, l.nofollow, l.ignored, l.unlinked, l.modified, l.anchored, l.attributed';
1521
-
1522
  // Prepare inner join
1523
  $inner_join = ' INNER JOIN '.$wpdb->prefix.'wplnst_urls_status s ON u.url_id = s.url_id ';
1524
-
1525
  // Prepare right join
1526
  $right_join = ' RIGHT JOIN '.$wpdb->prefix.'wplnst_urls_locations l ON s.url_id = l.url_id AND s.scan_id = l.scan_id';
1527
-
1528
  /* Prepare where */
1529
-
1530
  // Base conditions
1531
  $where = 's.scan_id = '.$scan_id.' AND u.url_id = s.url_id AND s.phase = "end"';
1532
-
1533
  // Check URL id
1534
  if (!empty($url_id)) {
1535
  $where .= ' AND u.url_id = '.((int) $url_id);
1536
-
1537
  // Check status level
1538
  } elseif (isset($status_level) && false !== $status_level) {
1539
  $where .= ' AND s.status_level = "'.esc_sql($status_level).'"';
1540
-
1541
  // Check status code
1542
  } elseif (isset($status_code) && false !== $status_code) {
1543
  $where .= ' AND s.status_code = "'.esc_sql($status_code).'"';
1544
  }
1545
-
1546
  // Check object type
1547
- if (isset($object_type) && false !== $object_type)
1548
  $where .= ' AND l.object_type = "'.esc_sql($object_type).'"';
1549
-
 
1550
  // Check object post type
1551
- if (isset($object_post_type) && false !== $object_post_type)
1552
- $where .= ' AND l.object_post_type = "'.esc_sql($object_post_type).'"';
1553
-
 
1554
  // Check link type
1555
- if (isset($link_type) && false !== $link_type)
1556
  $where .= ' AND l.link_type = "'.esc_sql($link_type).'"';
1557
-
 
1558
  // Check ignored type
1559
  if (isset($ignored_type) && false !== $ignored_type) {
1560
- if ('oir' == $ignored_type)
1561
  $where .= ' AND l.ignored = 1';
 
1562
  } else {
1563
  $where .= ' AND l.ignored = 0';
1564
  }
1565
-
1566
  // SEO link type
1567
- if (isset($seo_link_type) && false !== $seo_link_type)
1568
  $where .= ' AND l.nofollow = '.(('nf' == $seo_link_type)? '1' : '0');
1569
-
 
1570
  // Protocol type
1571
- if (isset($protocol_type) && false !== $protocol_type)
1572
  $where .= ('rel' == $protocol_type)? ' AND l.protorel = 1' : ' AND u.scheme = "'.esc_sql($protocol_type).'" AND l.protorel = 0';
1573
-
 
1574
  // Special type
1575
  if (isset($special_type) && false !== $special_type) {
1576
  if ('rel' == $special_type) {
@@ -1583,7 +1652,7 @@ class WPLNST_Core_Scans {
1583
  $where .= ' AND l.malformed = 1';
1584
  }
1585
  }
1586
-
1587
  // Action type
1588
  if (isset($action_type) && false !== $action_type) {
1589
  if ('unl' == $action_type) {
@@ -1596,11 +1665,12 @@ class WPLNST_Core_Scans {
1596
  $where .= ' AND s.rechecked = 1';
1597
  }
1598
  }
1599
-
1600
  // Check destination type
1601
- if (isset($dest_type) && false !== $dest_type && 'all' != $dest_type)
1602
  $where .= ' AND u.scope = "'.esc_sql($dest_type).'"';
1603
-
 
1604
  // Check search URL
1605
  if (isset($search_url) && false !== $search_url && '' !== $search_url) {
1606
  $like = esc_sql(addcslashes($search_url, '_%\\'));
@@ -1611,20 +1681,20 @@ class WPLNST_Core_Scans {
1611
  $where .= ' AND (u.url'.$op.' OR s.redirect_url'.$op.')';
1612
  }
1613
  }
1614
-
1615
  // Check search anchor
1616
  if (isset($search_anchor) && false !== $search_anchor && '' !== $search_anchor) {
1617
  $op = ('f' == $search_anchor_type)? ' = "'.esc_sql($search_anchor).'"' : ' LIKE "'.(('s' == $search_anchor_type || 'm' == $search_anchor_type)? '%' : '').esc_sql(addcslashes($search_anchor, '_%\\')).(('p' == $search_anchor_type || 'm' == $search_anchor_type)? '%' : '').'"';
1618
  $where .= ' AND l.anchor'.$op;
1619
  }
1620
-
1621
  // Check first order by date
1622
  if (isset($order_type) && false !== $order_type) {
1623
-
1624
  // Change default order
1625
  if (in_array($order_type, array_keys(WPLNST_Core_Types::get_crawl_order()))) {
1626
  $order_by = 'l.object_date_gmt '.(('asc' == $order_type)? 'ASC' : 'DESC');
1627
-
1628
  // Orders
1629
  } else {
1630
  if ('dma' == $order_type) {
@@ -1641,14 +1711,14 @@ class WPLNST_Core_Scans {
1641
  $order_by = 's.total_bytes DESC';
1642
  }
1643
  }
1644
-
1645
  // Default order
1646
  } else {
1647
  $order_date = (isset($order_date) && in_array(strtoupper($order_date), array('ASC', 'DESC')))? strtoupper($order_date) : 'DESC';
1648
  $order_by = 'l.object_date_gmt '.$order_date;
1649
  }
1650
-
1651
-
1652
  // Done
1653
  return $this->pagination(array(
1654
  'paged' => $paged,
@@ -1667,47 +1737,53 @@ class WPLNST_Core_Scans {
1667
  * Retrieve scan locations
1668
  */
1669
  public function get_scan_locations($args) {
1670
-
1671
  // Globals
1672
  global $wpdb;
1673
-
1674
  // Check arguments
1675
- if (empty($args) || !is_array($args))
1676
  return false;
1677
-
 
1678
  // Extract parameters
1679
  extract($args);
1680
-
1681
  // Check scan id
1682
  $scan_id = empty($scan_id)? false : (int) $scan_id;
1683
- if (empty($scan_id))
1684
  return false;
1685
-
 
1686
  // Check url id
1687
  $url_id = empty($url_id)? false : (is_array($url_id)? array_map('intval', $url_id) : (int) $url_id);
1688
- if (empty($url_id))
1689
  return false;
1690
-
 
1691
  // URL id where
1692
  $url_id_where = is_array($url_id)? ' IN ('.implode(', ', $url_id).')' : ' = '.$url_id;
1693
-
1694
  // Others
1695
  $where = '';
1696
-
1697
  // Check object type
1698
- if (!empty($object_type))
1699
  $where .= ' AND object_type = "'.esc_sql($object_type).'"';
1700
-
 
1701
  // Check page
1702
  $paged = empty($paged)? 1 : (int) $paged;
1703
- if (empty($paged))
1704
  $paged = 1;
1705
-
 
1706
  // Check elements per page
1707
  $per_page = isset($per_page)? (int) $per_page : (int) get_user_option('wplnst_scan_locations_per_page');
1708
- if (empty($per_page))
1709
  $per_page = 25;
1710
-
 
1711
  // Done
1712
  return $this->pagination(array(
1713
  'paged' => $paged,
@@ -1726,13 +1802,13 @@ class WPLNST_Core_Scans {
1726
  * Retrieve single scan location
1727
  */
1728
  public function get_scan_location_by_id($loc_id) {
1729
-
1730
  // Global
1731
  global $wpdb;
1732
-
1733
  // Cast param
1734
  $loc_id = (int) $loc_id;
1735
-
1736
  // Perform query and return result
1737
  $locations = $wpdb->get_results($wpdb->prepare('SELECT * FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE loc_id = %d', $loc_id));
1738
  return (!empty($locations) && is_array($locations) && 1 == count($locations))? $locations[0] : false;
@@ -1744,10 +1820,10 @@ class WPLNST_Core_Scans {
1744
  * Retrieve multiple scan locations
1745
  */
1746
  public function get_scan_locations_by_ids($loc_ids) {
1747
-
1748
  // Global
1749
  global $wpdb;
1750
-
1751
  // Perform query and return result
1752
  $locations = $wpdb->get_results('SELECT * FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE loc_id IN ('.implode(', ', array_map('intval', $loc_ids)).')');
1753
  return (empty($locations) || !is_array($locations))? false : $locations;
@@ -1759,10 +1835,10 @@ class WPLNST_Core_Scans {
1759
  * Retrieve array info of location marks
1760
  */
1761
  public function get_scan_location_marks($scan_id, $loc_id) {
1762
-
1763
  // Global
1764
  global $wpdb;
1765
-
1766
  // Default
1767
  $marks = array(
1768
  'url' => '',
@@ -1775,33 +1851,34 @@ class WPLNST_Core_Scans {
1775
  'redirs' => false,
1776
  'redirs_count' => '1 redirect',
1777
  );
1778
-
1779
  // Retrieve row
1780
  $row = $wpdb->get_row($wpdb->prepare('SELECT u.url, u.scheme, l.relative, l.absolute, l.spaced, l.malformed, l.protorel, s.status_level, s.redirect_url_id, s.redirect_url, s.redirect_steps FROM '.$wpdb->prefix.'wplnst_urls AS u, '.$wpdb->prefix.'wplnst_urls_locations AS l, '.$wpdb->prefix.'wplnst_urls_status AS s WHERE l.loc_id = %d AND l.scan_id = %d AND u.url_id = l.url_id AND s.url_id = l.url_id AND s.scan_id = %d LIMIT 1', $loc_id, $scan_id, $scan_id));
1781
  if (!empty($row) && is_object($row)) {
1782
-
1783
  // Copy URL
1784
  $marks['url'] = esc_html($row->url);
1785
-
1786
  // Check HTTPS
1787
  $marks['https'] = ('https' == $row->scheme);
1788
-
1789
  // Link form
1790
  $marks['relative'] = (1 == $row->relative);
1791
  $marks['absolute'] = (1 == $row->absolute);
1792
  $marks['spaced'] = (1 == $row->spaced);
1793
  $marks['malformed'] = (1 == $row->malformed);
1794
  $marks['protorel'] = (1 == $row->protorel);
1795
-
1796
  // Redirs
1797
  $marks['redirs'] = ('3' == $row->status_level && $row->redirect_url_id > 0 && !empty($row->redirect_url));
1798
  if ($marks['redirs']) {
1799
  $redirs_steps = @json_decode($row->redirect_steps, true);
1800
- if (!empty($redirs_steps) && is_array($redirs_steps) && count($redirs_steps) > 1)
1801
  $marks['redirs_count'] = count($redirs_steps).' redirects';
 
1802
  }
1803
  }
1804
-
1805
  // Done
1806
  return $marks;
1807
  }
@@ -1819,30 +1896,32 @@ class WPLNST_Core_Scans {
1819
  * - no_cache
1820
  */
1821
  public function pagination($args) {
1822
-
1823
  // Globals
1824
  global $wpdb;
1825
-
1826
  // Check arguments
1827
- if (empty($args) || !is_array($args))
1828
  return false;
1829
-
 
1830
  // Extract parameters
1831
  extract($args);
1832
-
1833
  // Check basic params
1834
- if (empty($sql) || empty($fields))
1835
  return false;
1836
-
 
1837
  // Totals method and cache
1838
  $calc_rows = !empty($calc_rows) && (true === $calc_rows);
1839
  $no_cache = !empty($no_cache) && (true === $no_cache);
1840
-
1841
  // Calculating offset
1842
  $paged = empty($paged)? 1 : (int) $paged;
1843
  $per_page = empty($per_page)? 10 : (int) $per_page;
1844
  $offset = (int) (($paged - 1) * $per_page);
1845
-
1846
  // Default
1847
  $results = array(
1848
  'paged' => $paged,
@@ -1856,59 +1935,62 @@ class WPLNST_Core_Scans {
1856
  'no_cache' => $no_cache,
1857
  'rows' => array(),
1858
  );
1859
-
1860
  // Timer
1861
  $time_start = microtime(true);
1862
-
1863
  // Count rows method
1864
  if (!$calc_rows) {
1865
-
1866
  // Prepare COUNT sql
1867
  $sql_count = str_replace('$$$fields$$$', 'COUNT(*)', $sql);
1868
- if ($no_cache)
1869
  $sql_count = str_replace('SELECT ', 'SELECT SQL_NO_CACHE ', $sql_count);
1870
-
 
1871
  // Obtain totals
1872
  $results['total_rows'] = (int) $wpdb->get_var($sql_count);
1873
-
1874
  // Calc
1875
  } else {
1876
-
1877
- // Replace SELECT
1878
  $sql = str_replace('SELECT ', 'SELECT SQL_CALC_FOUND_ROWS ', $sql);
1879
  }
1880
-
1881
  // Check NO CACHE
1882
- if ($no_cache)
1883
  $sql = str_replace('SELECT ', 'SELECT SQL_NO_CACHE ', $sql);
1884
-
 
1885
  // Set fields
1886
  $sql = str_replace('$$$fields$$$', $fields, $sql);
1887
-
1888
  // Add ORDER and LIMIT
1889
  $sql .= (empty($order_by)? '' : ' ORDER BY '.$order_by).' LIMIT '.$offset.', '.$per_page;
1890
  //echo $sql;
1891
  // Perform query
1892
  $results['rows'] = $wpdb->get_results($sql);
1893
-
1894
  // Calc rows
1895
- if ($calc_rows)
1896
  $results['total_rows'] = (int) $wpdb->get_var('SELECT FOUND_ROWS()');
1897
-
 
1898
  // End timer
1899
  $results['time'] = microtime(true) - $time_start;
1900
  //echo '<br />'.$results['time'].' s';
1901
  // Total pages
1902
  $results['total_pages'] = empty($results['total_rows'])? 0 : ceil($results['total_rows'] / $per_page);
1903
-
1904
  // Queried rows
1905
  if (!empty($results['rows']) && is_array($results['rows'])) {
1906
-
1907
  // Total rows in page
1908
  $results['rows_page'] = count($results['rows']);
1909
  $results['rows_end'] = $results['rows_start'] + $results['rows_page'] - 1;
1910
  }
1911
-
1912
  // Done
1913
  return (object) $results;
1914
  }
1
  <?php
2
 
3
  /**
4
+ * Scans class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Scans {
10
 
19
  * Retrieve existing scans
20
  */
21
  public function get_scans($args) {
22
+
23
  // Globals
24
  global $wpdb;
25
+
26
  // Prepare args
27
  $args = array_merge(array(
28
  'setup_rows' => true,
29
  'setup_names' => false,
30
  'no_cache' => false,
31
  ), $args);
32
+
33
  // Set vars
34
  extract($args);
35
+
36
  // Params
37
  $where = ' WHERE 1 = 1';
38
  $limit_rows = false;
39
+
40
  // Check scan id
41
+ if (!empty($scan_id)) {
42
  $where .= ' AND scan_id = '.((int) $scan_id);
43
+ }
44
+
45
  // Check limit
46
  if (isset($limit)) {
47
  $check = array_map('intval', array_map('trim', explode(',', $limit)));
48
  if (1 == count($check)) {
49
+ if ($check[0] > 0) {
50
  $limit_rows = $check[0];
51
+ }
52
  } elseif (2 == count($check)) {
53
+ if ($check[0] > 0 || $check[1] > 0) {
54
  $limit_rows = $check[0].', '.$check[1];
55
+ }
56
  }
57
  }
58
+
59
  // Check single row
60
  if (1 === $limit_rows) {
61
+
62
  // Perform query
63
  $sql = 'SELECT'.(empty($no_cache)? '' : ' SQL_NO_CACHE').' * FROM '.$wpdb->prefix.'wplnst_scans'.$where.(empty($order_by)? '' : ' ORDER BY '.$order_by).' LIMIT 1';
64
  $results = (object) array('rows' => $wpdb->get_results($sql));
65
+
66
  // Multiple rows
67
  } else {
68
+
69
  // Check page
70
  $paged = empty($paged)? 1 : (int) $paged;
71
+ if (empty($paged)) {
72
  $paged = 1;
73
+ }
74
+
75
  // Check elements per page
76
  $per_page = isset($per_page)? (int) $per_page : (int) get_user_option('wplnst_scans_per_page');
77
+ if (empty($per_page)) {
78
  $per_page = WPLNST_Core_Types::scans_per_page;
79
+ }
80
+
81
  // Execute query
82
  $results = $this->pagination(array(
83
  'paged' => $paged,
89
  'no_cache' => false,
90
  ));
91
  }
92
+
93
  // Check setup
94
+ if (!$setup_rows || empty($results->rows)) {
95
  return $results;
96
+ }
97
+
98
  // Prepare rows
99
  $rows = array();
100
+ foreach ($results->rows as $row) {
101
  $rows[] = $this->setup_row_scan($row, $setup_names);
102
+ }
103
  $results->rows = $rows;
104
+
105
  // Done
106
  return $results;
107
  }
112
  * Return scan by its id
113
  */
114
  public function get_scan_by_id($scan_id, $setup_names = false, $no_cache = false) {
115
+
116
  // Retrieve scans list
117
  $scans = $this->get_scans(array('scan_id' => $scan_id, 'setup_rows' => true, 'setup_names' => $setup_names, 'no_cache' => $no_cache, 'limit' => 1));
118
+
119
  // Count elements, return first or false
120
  return (!empty($scans->rows) && is_array($scans->rows) && 1 == count($scans->rows))? $scans->rows[0] : false;
121
  }
126
  * Setup a scan database row
127
  */
128
  public function setup_row_scan($row, $names = false) {
129
+
130
  // Cache post types
131
  static $post_types;
132
+ if (!isset($post_types)) {
133
  $post_types = WPLNST_Core_Types::get_post_types();
134
+ }
135
+
136
  // Cache post types keys
137
  static $post_types_keys;
138
+ if (!isset($post_types_keys)) {
139
  $post_types_keys = array_keys($post_types);
140
+ }
141
+
142
  // Cache post status
143
  static $post_status_keys;
144
+ if (!isset($post_status_keys)) {
145
  $post_status_keys = array_keys(WPLNST_Core_Types::get_post_status());
146
+ }
147
+
148
  // Cache status level
149
  static $status_levels;
150
+ if (!isset($status_levels)) {
151
  $status_levels = WPLNST_Core_Types::get_status_levels();
152
+ }
153
+
154
  // Cache status levels keys
155
  static $status_levels_keys;
156
+ if (!isset($status_levels_keys)) {
157
  $status_levels_keys = array_keys($status_levels);
158
+ }
159
+
160
  // Cache status codes
161
  static $status_codes_raw;
162
+ if (!isset($status_codes_raw)) {
163
  $status_codes_raw = WPLNST_Core_Types::get_status_codes_raw();
164
+ }
165
+
166
  // Cache status codes keys
167
  static $status_codes_keys;
168
+ if (!isset($status_codes_keys)) {
169
  $status_codes_keys = array_keys($status_codes_raw);
170
+ }
171
+
172
  // Scan object
173
  $scan = new stdClass;
174
  $scan->row = $row;
175
+
176
+
177
  /* scan values */
178
+
179
  // Cast fields
180
  $scan->id = (int) $row->scan_id;
181
  $scan->name = $row->name;
182
  $scan->status = $row->status;
183
  $scan->ready = (1 == (int) $row->ready);
184
  $scan->hash = $row->hash;
185
+
186
  // Decode config json field
187
  $config = @json_decode($row->config, true);
188
+
189
  // General tab
190
  $scan->destination_type = WPLNST_Core_Types::check_array_value($config, 'destination_type', array_keys(WPLNST_Core_Types::get_destination_types()), 'all');
191
  $scan->time_scope = WPLNST_Core_Types::check_array_value($config, 'time_scope', array_keys(WPLNST_Core_Types::get_time_scopes()), 'anytime');
196
  $scan->notify_default = WPLNST_Core_Types::check_array_value($config, 'notify_default', true);
197
  $scan->notify_address = WPLNST_Core_Types::check_array_value($config, 'notify_address', true);
198
  $scan->notify_address_email = WPLNST_Core_Types::get_array_value($config, 'notify_address_email', '');
199
+
200
  // Content options tab
201
  $scan->post_types = (function_exists('did_action') && did_action('init'))? WPLNST_Core_Types::check_array_value($config, 'post_types', $post_types_keys, array()) : ((empty($config['post_types']) || !is_array($config['post_types']))? array() : $config['post_types']);
202
  $scan->post_status = WPLNST_Core_Types::check_array_value($config, 'post_status', $post_status_keys, array());
204
  $scan->comment_types = WPLNST_Core_Types::check_array_value($config, 'comment_types', array_keys(WPLNST_Core_Types::get_comment_types()), array());
205
  $scan->check_comments = (!empty($scan->comment_types) && is_array($scan->comment_types));
206
  $scan->check_blogroll = WPLNST_Core_Types::check_array_value($config, 'blogroll', true);
207
+
208
  // Links status tab
209
  $scan->status_levels = WPLNST_Core_Types::check_array_value($config, 'status_levels', $status_levels_keys, array());
210
  $scan->status_codes = WPLNST_Core_Types::check_array_value($config, 'status_codes', array_keys(WPLNST_Core_Types::get_status_codes_raw()), array());
211
+
212
  // Filters
213
  $scan->custom_fields = WPLNST_Core_Types::check_array_json($config, 'custom_fields');
214
  $scan->anchor_filters = WPLNST_Core_Types::check_array_json($config, 'anchor_filters');
216
  $scan->exclude_urls = WPLNST_Core_Types::check_array_json($config, 'exclude_urls');
217
  $scan->html_attributes = WPLNST_Core_Types::check_array_json($config, 'html_attributes');
218
  $scan->filtered_query = WPLNST_Core_Types::check_array_value($config, 'filtered_query', true);
219
+
220
+
221
  /* scan config values names */
222
+
223
  if ($names) {
224
+
225
  // Destination and Time scope
226
  $scan->destination_type_name = WPLNST_Core_Types::get_destination_type_name($scan->destination_type, 'all');
227
  $scan->time_scope_name = WPLNST_Core_Types::get_time_scope_name($scan->time_scope, 'anytime');
228
+
229
  // Links types
230
  $scan->link_types_names = WPLNST_Core_Types::get_link_types_names($scan->link_types);
231
+
232
  // Crawl order
233
  $scan->crawl_order_name = WPLNST_Core_Types::get_crawl_order_name($scan->crawl_order, 'desc');
234
+
235
  // Post types and status
236
  $scan->post_types_names = WPLNST_Core_Types::get_field_values_names($post_types, $scan->post_types);
237
  $scan->post_status_names = empty($scan->post_status)? array() : array_map('ucfirst', $scan->post_status);
238
+
239
  // A strict mode of post types names
240
  $scan->post_types_names_strict = array();
241
  foreach ($scan->post_types as $post_type_value) {
242
+ if (isset($post_types[$post_type_value])) {
243
  $scan->post_types_names_strict[] = esc_html($post_types[$post_type_value]).' (<code>'.esc_html($post_type_value).'</code>)';
244
+ }
245
  }
246
+
247
  // Comment types
248
  if ($scan->check_comments) {
249
  $scan->comment_types_names = WPLNST_Core_Types::get_comment_types_names($scan->comment_types);
253
  $scan->post_types_names[] = sprintf(__('%s and %s comments', 'wplnst'), $scan->comment_types_names[0], lcfirst($scan->comment_types_names[1]));
254
  }
255
  }
256
+
257
  // Check blogroll type
258
+ if ($scan->check_blogroll) {
259
  $scan->post_types_names[] = __('Blogroll', 'wplnst');
260
+ }
261
+
262
  // Links status combined
263
  $scan->links_status_names = WPLNST_Core_Types::get_links_status_names_combined($scan->status_levels, $scan->status_codes);
264
+
265
  // Links status levels
266
  $scan->status_levels_names = array();
267
  foreach ($scan->status_levels as $status_level) {
268
+ if (isset($status_levels[$status_level])) {
269
  $scan->status_levels_names[] = $status_level.'00s ' .$status_levels[$status_level];
270
+ }
271
  }
272
+
273
  // Links status codes
274
  $scan->status_codes_names = array();
275
  foreach ($scan->status_codes as $status_code) {
276
+ if (isset($status_codes_raw[$status_code])) {
277
  $scan->status_codes_names[] = $status_code.' ' .$status_codes_raw[$status_code];
278
+ }
279
  }
280
  }
281
+
282
+
283
  /* Prepare trace values */
284
+
285
  // Decode trace json field
286
  $trace = @json_decode($row->trace, true);
287
+ if (empty($trace) || !is_array($trace)) {
288
  $trace = array();
289
+ }
290
  $scan->trace = $trace;
291
+
292
+
293
  /* Prepare scan summary */
294
+
295
  $summary = @json_decode($row->summary, true);
296
+ if (empty($summary) || !is_array($summary)) {
297
  $summary = array();
298
+ }
299
  $scan->summary = $summary;
300
+
301
+
302
  /* Prepare threads values */
303
+
304
  // Decode threads json field
305
  $threads = @json_decode($row->threads, true);
306
+
307
  // Create new object
308
  $scan->threads = new stdClass;
309
+
310
  // Assign object properties
311
  $scan->threads->current = (empty($threads) || !is_array($threads))? array() : $threads;
312
  $scan->threads->max = (int) $row->max_threads;
313
  $scan->threads->connect_timeout = (int) $row->connect_timeout;
314
  $scan->threads->request_timeout = (int) $row->request_timeout;
315
+
316
  // Done
317
  return $scan;
318
  }
323
  * Remove existing scan data
324
  */
325
  public function delete_scan($scan_id) {
326
+
327
  // Globals
328
  global $wpdb;
329
+
330
  // Remove from main scans table
331
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
332
+
333
  // Remove from status table
334
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_status WHERE scan_id = %d', $scan_id));
335
+
336
  // Remove from locations table
337
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE scan_id = %d', $scan_id));
338
+
339
  // Remove from locations attributes table
340
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_locations_att WHERE scan_id = %d', $scan_id));
341
+
342
  // Remove from objects table
343
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = %d', $scan_id));
344
  }
349
  * Number of running scans
350
  */
351
  public function get_scans_play_count() {
352
+
353
  // Globals
354
  global $wpdb;
355
+
356
  // Perform query
357
  return (int) $wpdb->get_var('SELECT SQL_NO_CACHE COUNT(*) FROM '.$wpdb->prefix.'wplnst_scans WHERE status = "play"');
358
  }
372
  * Check if is ready to start a crawl
373
  */
374
  public static function is_scan_ready($scan) {
375
+
376
  // Initialize
377
  $result = array();
378
  $empty_post_types = false;
379
+
380
  // Check link types
381
+ if (empty($scan->link_types) || !is_array($scan->link_types)) {
382
  $result['link_types'] = __('There is not any <strong>link type</strong> selected, you need to select one or more.', 'wplnst');
383
+ }
384
+
385
  // Check post types
386
+ if (empty($scan->post_types) || !is_array($scan->post_types)) {
387
  $empty_post_types = true;
388
+ }
389
+
390
  // Check post status
391
  if (empty($scan->post_status) || !is_array($scan->post_status)) {
392
+ if (!$empty_post_types) {
393
  $result['post_status'] = __('Need to select any <strong>post status</strong> value for the selected post types.', 'wplnst');
394
+ }
395
  }
396
+
397
  // Check comments and blogroll
398
  if (!$scan->check_comments && !$scan->check_blogroll) {
399
  if ($empty_post_types) {
400
  $result['post_types'] = __('There is not any kind of <strong>post type</strong>, <strong>comments</strong> or <strong>blogroll</strong> selected.', 'wplnst');
401
  }
402
  }
403
+
404
  // Check status levels and status codes
405
+ if ((empty($scan->status_levels) || !is_array($scan->status_levels)) && (empty($scan->status_codes) || !is_array($scan->status_codes))) {
406
  $result['link_status'] = __('Missing selection of any <strong>links status</strong> level or status code.', 'wplnst');
407
+ }
408
+
409
  // Done
410
  return empty($result)? true : $result;
411
  }
416
  * Update scan ready status
417
  */
418
  public function update_scan_ready($scan_id, $ready) {
419
+
420
  // Globals
421
  global $wpdb;
422
+
423
  // Perform query
424
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('ready' => $ready? 1 : 0), array('scan_id' => $scan_id));
425
  }
432
  public function remove_stopped_time($scan_id) {
433
  // Globals
434
  global $wpdb;
435
+
436
  // Perform query
437
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('stopped_at' => '0000-00-00 00:00:00'), array('scan_id' => $scan_id));
438
  }
443
  * Obtains fresh scan trace data
444
  */
445
  public function get_scan_trace($scan_id, $field = false) {
446
+
447
  // Globals
448
  global $wpdb;
449
 
451
  $trace = $wpdb->get_var($wpdb->prepare('SELECT SQL_NO_CACHE trace FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
452
  $trace = @json_decode($trace, true);
453
  $trace = (empty($trace) || !is_array($trace))? array() : $trace;
454
+
455
  // Check field or all values
456
  return (false !== $field)? (isset($trace[$field])? $trace[$field] : false) : $trace;
457
  }
462
  * Update scan trace values
463
  */
464
  public function update_scan_trace($scan_id, $values) {
465
+
466
  // Globals
467
  global $wpdb;
468
+
469
  // Merge trace values
470
  $trace = array_merge($this->get_scan_trace($scan_id), $values);
471
+
472
  // Update trace values
473
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('trace' => @json_encode($trace)), array('scan_id' => $scan_id));
474
  }
479
  * Retrieve scan summary
480
  */
481
  public function get_scan_summary($scan_id) {
482
+
483
  // Globals
484
  global $wpdb;
485
+
486
  // Retrieve fresh summary data
487
  $summary = $wpdb->get_var($wpdb->prepare('SELECT SQL_NO_CACHE summary FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
488
  $summary = @json_decode($summary, true);
489
+
490
  // Check data
491
  return (empty($summary) || !is_array($summary))? array() : $summary;
492
  }
497
  * Remove scan summary data by prefixed keys
498
  */
499
  public function remove_scan_summary_prefixed($scan_id, $prefixes) {
500
+
501
  // Globals
502
  global $wpdb;
503
+
504
  // Check value
505
+ if (empty($prefixes)) {
506
  return;
507
+ }
508
+
509
  // Check array
510
+ if (!is_array($prefixes)) {
511
  $prefixes = array($prefixes);
512
+ }
513
+
514
  // Current data
515
  $summary = $this->get_scan_summary($scan_id);
516
  if (!empty($summary)) {
517
+
518
  // Initialize
519
  $summary2 = array();
520
 
521
  // Enum summary data
522
  foreach ($summary as $key => $value) {
523
+
524
  // Check prefixes
525
  $match = false;
526
  foreach ($prefixes as $prefix) {
529
  break;
530
  }
531
  }
532
+
533
  // Removed
534
+ if ($match) {
535
  continue;
536
+ }
537
+
538
  // Copy data
539
  $summary2[$key] = $value;
540
  }
541
+
542
  // Check summary update
543
+ if (count($summary) != count($summary2)) {
544
  $this->update_scan_summary($scan_id, $summary2, false);
545
+ }
546
  }
547
  }
548
 
552
  * Update scan summary data
553
  */
554
  public function update_scan_summary($scan_id, $values, $merge = true) {
555
+
556
  // Globals
557
  global $wpdb;
558
+
559
  // Check previous summary
560
  $summary = $this->get_scan_summary($scan_id);
561
+
562
  // Merge data
563
  $summary = (empty($summary) || !$merge)? $values : array_merge($summary, $values);
564
+
565
  // Update data
566
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('summary' => @json_encode($summary)), array('scan_id' => $scan_id));
567
  }
572
  * Update URL info for summary
573
  */
574
  public function set_scan_summary_status_codes($scan_id, $status_levels, $status_codes, $final = false) {
575
+
576
  // Globals
577
  global $wpdb;
578
+
579
  // Not the last
580
  if (!$final) {
581
+
582
  // Check timestamp
583
  $timestamp = $this->get_scan_trace($scan_id, 'summary_status_codes');
584
+ if (false !== $timestamp && (time() - $timestamp) < wplnst_get_nsetting('summary_status')) {
585
  return;
586
+ }
587
+
588
  // Update timestamp
589
  $this->update_scan_trace($scan_id, array('summary_status_codes' => time()));
590
  }
591
+
592
  // Check levels
593
+ if (!empty($status_levels) && is_array($status_levels)) {
594
  $where_levels = 's.status_level IN ("0", "'.implode('", "', array_map('esc_sql', $status_levels)).'")';
595
+ }
596
+
597
  // Check codes
598
+ if (!empty($status_codes) && is_array($status_codes)) {
599
  $where_codes = 's.status_code IN ("0", "'.implode('", "', array_map('esc_sql', $status_codes)).'")';
600
+ }
601
+
602
  // Compose combined
603
  if (isset($where_levels) && isset($where_codes)) {
604
  $where = ' AND ('.$where_levels.' OR '.$where_codes.')';
605
+
606
  // Only levels
607
  } elseif (isset($where_levels)) {
608
  $where = ' AND '.$where_levels;
609
+
610
  // Only codes
611
  } elseif (isset($where_codes)) {
612
  $where = ' AND '.$where_codes;
613
+
614
  // Error
615
  } else {
616
  return;
617
  }
618
+
619
  // Initialize
620
  $total = 0;
621
  $codes = array();
622
  $levels = array();
623
+
624
  // Retrieve totals of codes for not ignored locations
625
  $results = $wpdb->get_results($wpdb->prepare('SELECT s.status_code, COUNT(*) total FROM '.$wpdb->prefix.'wplnst_urls_status s RIGHT JOIN '.$wpdb->prefix.'wplnst_urls_locations l ON s.url_id = l.url_id AND s.scan_id = l.scan_id WHERE s.scan_id = %d '.$where.' AND s.phase = "end" AND l.ignored = 0 GROUP BY status_code', $scan_id));
626
+
627
  // Cast data to array
628
  if (!empty($results) && is_array($results)) {
629
+
630
  // Enum code results
631
  foreach ($results as $result) {
632
+
633
  // Sum all codes
634
  $total += (int) $result->total;
635
+
636
  // Total for this code
637
  $codes[$result->status_code] = (int) $result->total;
638
+
639
  // Total for this level
640
  $level_key = mb_substr($result->status_code, 0, 1);
641
  $levels[$level_key] = isset($levels[$level_key])? $levels[$level_key] + $codes[$result->status_code] : $codes[$result->status_code];
642
  }
643
  }
644
+
645
  // Prepare to summary
646
  $summary_keys = array();
647
+
648
  // Prefix code keys
649
+ foreach ($codes as $key => $value) {
650
  $summary_keys['status_code_'.$key] = $value;
651
+ }
652
+
653
  // Prefix level keys
654
+ foreach ($levels as $key => $value) {
655
  $summary_keys['status_level_'.$key] = $value;
656
+ }
657
+
658
  // Total results
659
  $summary_keys['status_total'] = $total;
660
+
661
  // Remove old summary status values
662
  $this->remove_scan_summary_prefixed($scan_id, array('status_code_', 'status_level_'));
663
+
664
  // Update summary data
665
  $this->update_scan_summary($scan_id, $summary_keys);
666
  }
671
  * Update URL info for summary
672
  */
673
  public function set_scan_summary_urls_phases($scan_id, $final = false) {
674
+
675
  // Globals
676
  global $wpdb;
677
+
678
  // Not the last
679
  if (!$final) {
680
+
681
  // Check timestamp
682
  $timestamp = $this->get_scan_trace($scan_id, 'summary_url_phases');
683
+ if (false !== $timestamp && (time() - $timestamp) < wplnst_get_nsetting('summary_phases')) {
684
  return;
685
+ }
686
+
687
  // Update timestamp
688
  $this->update_scan_trace($scan_id, array('summary_url_phases' => time()));
689
  }
690
+
691
  // Initialize
692
  $phases = array();
693
+
694
  // Retrieve totals of phases
695
  $results = $wpdb->get_results($wpdb->prepare('SELECT phase, COUNT(*) total FROM '.$wpdb->prefix.'wplnst_urls_status WHERE scan_id = %d GROUP BY phase', $scan_id));
696
+
697
  // Cast data to array
698
  if (!empty($results) && is_array($results)) {
699
+ foreach ($results as $result) {
700
  $phases[$result->phase] = (int) $result->total;
701
+ }
702
  }
703
+
704
  // Merge default values
705
  $phases = array_merge(array(
706
  'wait' => 0,
710
  'discard' => 0,
711
  'failed' => 0
712
  ), $phases);
713
+
714
  // Sum redir to wait
715
  $phases['wait'] += $phases['redir'];
716
+
717
  // New values combined
718
  $phases['processed'] = $phases['end'] + $phases['discard'] + $phases['failed'];
719
+
720
  // Prefix keys
721
  $summary_phases = array();
722
+ foreach ($phases as $key => $value) {
723
  $summary_phases['urls_phase_'.$key] = $value;
724
+ }
725
+
726
  // Update summary data
727
  $this->update_scan_summary($scan_id, $summary_phases);
728
  }
731
 
732
  /**
733
  * Obtains the total match objects and update summary
734
+ */
735
  public function set_scan_summary_objects_match($scan_id, $object_type, $final = false) {
736
+
737
  // Globals
738
  global $wpdb;
739
+
740
  // Not the last
741
  if (!$final) {
742
+
743
  // Check timestamp
744
  $timestamp = $this->get_scan_trace($scan_id, 'summary_objects_match');
745
+ if (false !== $timestamp && (time() - $timestamp) < wplnst_get_nsetting('summary_objects')) {
746
  return;
747
+ }
748
+
749
  // Update timestamp
750
  $this->update_scan_trace($scan_id, array('summary_objects_match' => time()));
751
  }
752
+
753
  // Perform query
754
  $objects_match = (int) $wpdb->get_var($wpdb->prepare('SELECT COUNT(DISTINCT object_id) FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE scan_id = %d AND object_type = %s', $scan_id, $object_type));
755
+
756
  // Update summary data
757
  $this->update_scan_summary($scan_id, array('objects_match_'.$object_type => $objects_match));
758
  }
764
  * This works at the end of an scan crawling process
765
  */
766
  public function set_scan_final_threads_options($scan_id, $args) {
767
+
768
  // Globals
769
  global $wpdb;
770
+
771
  $args = array_merge(array(
772
  'max_threads' => 0,
773
  'connect_timeout' => 0,
774
  'request_timeout' => 0,
775
  ), $args);
776
+
777
  // Prepare update
778
  $update = array(
779
  'max_threads' => wplnst_get_nsetting('max_threads', $args['max_threads']),
780
  'connect_timeout' => wplnst_get_nsetting('connect_timeout', $args['connect_timeout']),
781
  'request_timeout' => wplnst_get_nsetting('request_timeout', $args['request_timeout']),
782
  );
783
+
784
  // Update
785
  return $wpdb->update($wpdb->prefix.'wplnst_scans', $update, array('scan_id' => $scan_id));
786
  }
796
  * Obtains fresh scan status data
797
  */
798
  public function get_scan_status($scan_id) {
799
+
800
  // Globals
801
  global $wpdb;
802
+
803
  // Return status
804
  return $wpdb->get_var($wpdb->prepare('SELECT SQL_NO_CACHE status FROM '.$wpdb->prefix.'wplnst_scans WHERE scan_id = %d', $scan_id));
805
  }
810
  * Stop any playing scan
811
  */
812
  public function stop_playing_scans() {
813
+
814
  // Globals
815
  global $wpdb;
816
+
817
  // Perform query
818
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'stop'), array('status' => 'play'));
819
  }
824
  * Queue a given scan
825
  */
826
  public function queue_scan($scan_id) {
827
+
828
  // Globals
829
  global $wpdb;
830
+
831
  // Perform query
832
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'queued', 'enqueued_at' => current_time('mysql', true)), array('scan_id' => $scan_id));
833
  }
838
  * Unqueue scan, cast to wait
839
  */
840
  public function unqueue_scan($scan_id) {
841
+
842
  // Globals
843
  global $wpdb;
844
+
845
  // Perform query
846
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'wait'), array('scan_id' => $scan_id));
847
  }
852
  * Play a given scan
853
  */
854
  public function play_scan($scan_id, $continued = false) {
855
+
856
  // Globals
857
  global $wpdb;
858
+
859
  // Decide field
860
  $time_field = $continued? 'continued_at' : 'started_at';
861
+
862
  // Perform query
863
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'play', $time_field => current_time('mysql', true)), array('scan_id' => $scan_id));
864
  }
869
  * Stop a given scan
870
  */
871
  public function stop_scan($scan_id) {
872
+
873
  // Globals
874
  global $wpdb;
875
+
876
  // Perform query
877
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'stop', 'stopped_at' => current_time('mysql', true)), array('scan_id' => $scan_id));
878
  }
883
  * Terminated scan
884
  */
885
  public function end_scan($scan_id) {
886
+
887
  // Globals
888
  global $wpdb;
889
+
890
  // Perform query
891
  return $wpdb->update($wpdb->prefix.'wplnst_scans', array('status' => 'end', 'finished_at' => current_time('mysql', true)), array('scan_id' => $scan_id));
892
  }
902
  * Replacement function of WP API because we need meta_id
903
  */
904
  public function get_post_metas($post_id) {
905
+
906
  // Globals
907
  global $wpdb;
908
+
909
  // Check keys input
910
+ if (!empty($keys) && !is_array($keys)) {
911
  $keys = array($keys);
912
+ }
913
+
914
  // Retrieve metas
915
  $rows = $wpdb->get_results($wpdb->prepare('SELECT * FROM '.$wpdb->postmeta.' WHERE post_id = %d ORDER BY meta_id ASC', $post_id));
916
+
917
  // Check results
918
  if (!empty($rows) && is_array($rows)) {
919
+
920
  // Initialize
921
  $metas = array();
922
+
923
  // Enum rrows
924
  foreach ($rows as $row) {
925
+
926
  // Check meta key
927
+ if (empty($row->meta_key)) {
928
  continue;
929
+ }
930
+
931
  // Check by name
932
+ if (!isset($metas[$row->meta_key])) {
933
  $metas[$row->meta_key] = array();
934
+ }
935
+
936
  // Add value
937
  $metas[$row->meta_key][$row->meta_id] = $row->meta_value;
938
  }
939
+
940
  // Done
941
  return $metas;
942
  }
943
+
944
  // Not found
945
  return false;
946
  }
951
  * Register by identifiers before process the object
952
  */
953
  public function register_scan_object($scan_id, $object_id, $object_type, $object_date_gmt = "0000-00-00 00:00:00") {
954
+
955
  // Globals
956
  global $wpdb;
957
+
958
  // Insert attempt
959
  return (1 == (int) $wpdb->query($wpdb->prepare('INSERT IGNORE INTO '.$wpdb->prefix.'wplnst_scans_objects SET scan_id = %d, object_id = %d, object_type = %s, object_date_gmt = %s', $scan_id, $object_id, $object_type, $object_date_gmt)));
960
  }
965
  * Check if exists an scan object
966
  */
967
  public function scan_object_exists($scan_id, $object_id, $object_type) {
968
+
969
  // Globals
970
  global $wpdb;
971
+
972
  // Number of occurrences
973
  return (1 == (int) $wpdb->get_var($wpdb->prepare('SELECT SQL_NO_CACHE COUNT(*) FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = %d AND object_id = %d AND object_type = %s', $scan_id, $object_id, $object_type)));
974
  }
979
  * Retrieve object identifiers based on type and same date
980
  */
981
  public function get_scan_objects_ids_by_date($scan_id, $object_type, $object_date_gmt) {
982
+
983
  // Globals
984
  global $wpdb;
985
+
986
  // Number of occurrences
987
  return $wpdb->get_col($wpdb->prepare('SELECT SQL_NO_CACHE object_id FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = %d AND object_type = %s AND object_date_gmt = %s', $scan_id, $object_type, $object_date_gmt));
988
  }
993
  * Return the amount of registered objects
994
  */
995
  public function get_scan_objects_count($scan_id, $object_type) {
996
+
997
  // Globals
998
  global $wpdb;
999
+
1000
  // Insert attempt
1001
  return (int) $wpdb->get_var($wpdb->prepare('SELECT COUNT(*) FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = %d AND object_type = %s', $scan_id, $object_type));
1002
  }
1007
  * Remove all scan registered objects
1008
  */
1009
  public function remove_scan_objects($scan_id) {
1010
+
1011
  // Globals
1012
  global $wpdb;
1013
+
1014
  // Insert attempt
1015
  return (int) $wpdb->get_var($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_scans_objects WHERE scan_id = %d', $scan_id));
1016
  }
1021
  * Retrieve scan URL data
1022
  */
1023
  public function get_scan_url($args) {
1024
+
1025
  // Globals
1026
  global $wpdb;
1027
+
1028
  // Arguments
1029
  extract($args);
1030
+
1031
  // Check by id
1032
  if (isset($id)) {
1033
+
1034
  // Check identifier
1035
  $id = (int) $id;
1036
  if (!empty($id)) {
1037
  $row = $wpdb->get_row($wpdb->prepare('SELECT '.(isset($no_cache)? 'SQL_NO_CACHE ' : '').'* FROM '.$wpdb->prefix.'wplnst_urls WHERE url_id = %d', $id));
1038
  return empty($row)? false : $row;
1039
  }
1040
+
1041
  // By URL string
1042
  } elseif (isset($url)) {
1043
+
1044
  // Retrieve URLs by hash
1045
  $rows = $wpdb->get_results($wpdb->prepare('SELECT '.(isset($no_cache)? 'SQL_NO_CACHE ' : '').'* FROM '.$wpdb->prefix.'wplnst_urls WHERE hash = %s ORDER BY url_id ASC', $this->get_url_hash($url)));
1046
+ if (empty($rows) || !is_array($rows) || 1 != count($rows)) {
1047
  return false;
1048
+ }
1049
+
1050
  // Done
1051
  return $rows[0];
1052
  }
1053
+
1054
  // Default
1055
  return false;
1056
  }
1061
  * Creates a 64 bytes hash to avoid URLs collisions
1062
  */
1063
  public function get_url_hash($url) {
1064
+
1065
  // First part
1066
  $hash = md5($url);
1067
+
1068
  // Another version
1069
  $url2 = array();
1070
+
1071
  // Special chars
1072
  static $special;
1073
+ if (!isset($special)) {
1074
  $special = array(";", "/", "?", ":", "@", "&", "=", "+", "$", ",", "-", "_", ".", "!", "~", "*", "'", "(", ")");
1075
+ }
1076
+
1077
  // Enum URL chars
1078
  $length = mb_strlen($url);
1079
  for ($i = 0; $i < $length; $i++) {
1080
  $char = mb_substr($url, $i, 1);
1081
+ if (!in_array($char, $special)) {
1082
  $url2[] = $char;
1083
+ }
1084
  }
1085
+
1086
  // Return combined hash
1087
  return $hash.md5(implode('', array_reverse($url2)));
1088
  }
1093
  * Retrieve next URL with next value
1094
  */
1095
  public function get_scan_url_waiting($scan_id) {
1096
+
1097
  // Retrieve by wait status
1098
  if (false !== ($rows = $this->get_scan_url_status(array(
1099
  'scan_id' => $scan_id,
1102
  'no_cache' => true,
1103
  'limit_rows' => 1,
1104
  )))) {
1105
+
1106
  // Retrieve url
1107
  $url = $this->get_scan_url(array('id' => $rows[0]->url_id, 'no_cache' => true));
1108
  if (false !== $url) {
1109
+
1110
  // Check a redirection
1111
  if ('redir' == $rows[0]->phase) {
1112
  $url->url = $rows[0]->redirect_url;
1113
  $url->redirection = true;
1114
  }
1115
  }
1116
+
1117
  // Done
1118
  return $url;
1119
  }
1120
+
1121
  // Default
1122
  return false;
1123
  }
1128
  * Add new URL scan
1129
  */
1130
  public function add_scan_url($link, $scan_id) {
1131
+
1132
  // Globals
1133
  global $wpdb;
1134
+
1135
  // Create hash
1136
  $hash = $this->get_url_hash($link['url']);
1137
+
1138
  // Prepare fields
1139
  $scheme = isset($link['scheme'])? mb_substr($link['scheme'], 0, 20) : '';
1140
  $host = isset($link['host'])? mb_substr($link['host'], 0, 255) : '';
1141
  $path = isset($link['path'])? mb_substr($link['path'], 0, 255) : '';
1142
  $query = isset($link['query'])? mb_substr($link['query'], 0, 255) : '';
1143
  $scope = isset($link['scope'])? $link['scope'] : '';
1144
+
1145
  // Add new scan status
1146
  $result = $wpdb->query($wpdb->prepare('INSERT IGNORE INTO '.$wpdb->prefix.'wplnst_urls SET url = %s, hash = %s, scheme = %s, host = %s, path = %s, query = %s, scope = %s, created_at = %s, last_scan_id = %d', $link['url'], $hash, $scheme, $host, $path, $query, $scope, current_time('mysql', true), $scan_id));
1147
  if (!empty($wpdb->insert_id)) {
1148
  return $wpdb->insert_id;
1149
+
1150
  // Collision?
1151
  } else {
1152
+
1153
  // Retrieve existing URL record
1154
  $rows = $wpdb->get_results($wpdb->prepare('SELECT url_id, url FROM '.$wpdb->prefix.'wplnst_urls WHERE hash = %s', $hash));
1155
+ if (empty($rows) || !is_array($rows) || 1 != count($rows)) {
1156
  return false;
1157
+ }
1158
+
1159
  // Return id only if URLs are the same
1160
  return ($rows[0]->url === $url)? $rows[0]->url_id : false;
1161
  }
1167
  * Update URL scan data
1168
  */
1169
  public function update_scan_url($url_id, $update) {
1170
+
1171
  // Globals
1172
  global $wpdb;
1173
+
1174
  // Update play value
1175
  return $wpdb->update($wpdb->prefix.'wplnst_urls', $update, array('url_id' => $url_id));
1176
  }
1181
  * Add location for scan url
1182
  */
1183
  public function add_scan_url_location($url_id, $scan_id, $link) {
1184
+
1185
  // Globals
1186
  global $wpdb;
1187
+
1188
  // Add new url
1189
  $wpdb->insert($wpdb->prefix.'wplnst_urls_locations', array(
1190
  'url_id' => $url_id,
1207
  'relative' => $link['relative']? 1 : 0,
1208
  'nofollow' => $link['nofollow']? 1 : 0,
1209
  ));
1210
+
1211
  // Result
1212
  return empty($wpdb->insert_id)? false : $wpdb->insert_id;
1213
  }
1218
  * Update location fields
1219
  */
1220
  public function update_scan_url_location($loc_id, $update) {
1221
+
1222
  // Globals
1223
  global $wpdb;
1224
+
1225
  // Update
1226
  return $wpdb->update($wpdb->prefix.'wplnst_urls_locations', $update, array('loc_id' => $loc_id));
1227
  }
1232
  * Update several locations
1233
  */
1234
  public function update_scan_url_locations($loc_ids, $update) {
1235
+ foreach ($loc_ids as $loc_id) {
1236
  $this->update_scan_url_location($loc_id, $update);
1237
+ }
1238
  }
1239
 
1240
 
1243
  * Update posts fields
1244
  */
1245
  public function update_scan_post($post_id, $update, $clean_cache = true) {
1246
+
1247
  // Globals
1248
  global $wpdb;
1249
+
1250
  // Update
1251
  $result = $wpdb->update($wpdb->posts, $update, array('ID' => $post_id));
1252
+
1253
  // Check cache
1254
+ if ($clean_cache) {
1255
  clean_post_cache($post_id);
1256
+ }
1257
+
1258
  // Done
1259
  return $result;
1260
  }
1265
  * Update meta associated to post
1266
  */
1267
  public function update_scan_post_meta($post_id, $meta_id, $content, $clean_cache = true) {
1268
+
1269
  // Globals
1270
  global $wpdb;
1271
+
1272
  // Update
1273
  $result = $wpdb->update($wpdb->postmeta, array('meta_value' => $content), array('meta_id' => $meta_id));
1274
+
1275
  // Check cache
1276
+ if ($clean_cache) {
1277
  clean_post_cache($post_id);
1278
+ }
1279
+
1280
  // Done
1281
  return $result;
1282
  }
1287
  * Update comment fields
1288
  */
1289
  public function update_scan_comment($comment_id, $update, $clean_cache = true) {
1290
+
1291
  // Globals
1292
  global $wpdb;
1293
+
1294
  // Update
1295
  $result = $wpdb->update($wpdb->comments, $update, array('comment_ID' => $comment_id));
1296
+
1297
  // Check cache
1298
+ if ($clean_cache) {
1299
  clean_comment_cache($comment_id);
1300
+ }
1301
+
1302
  // Done
1303
  return $result;
1304
  }
1309
  * Update bookmark fields
1310
  */
1311
  public function update_scan_bookmark($link_id, $update, $clean_cache = true) {
1312
+
1313
  // Globals
1314
  global $wpdb;
1315
+
1316
  // Update
1317
  $result = $wpdb->update($wpdb->links, $update, array('link_id' => $link_id));
1318
+
1319
  // Check cache
1320
+ if ($clean_cache) {
1321
  clean_bookmark_cache($link_id);
1322
+ }
1323
+
1324
  // Done
1325
  return $result;
1326
  }
1331
  * Update total content for a given URL
1332
  */
1333
  public function set_scan_url_status_total_content($url_id, $scan_id) {
1334
+
1335
  // Globals
1336
  global $wpdb;
1337
+
1338
  // Initialize
1339
  $total = array();
1340
+
1341
  // Retrieve total rows by object type
1342
  $results = $wpdb->get_results($wpdb->prepare('SELECT object_type, COUNT(*) total FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE url_id = %d AND scan_id = %d GROUP BY object_type', $url_id, $scan_id));
1343
+
1344
  // Cast data to array
1345
  if (!empty($results) && is_array($results)) {
1346
+ foreach ($results as $result) {
1347
  $total[$result->object_type] = (int) $result->total;
1348
+ }
1349
  }
1350
+
1351
  // Merge default values
1352
  $total = array_merge(array(
1353
  'posts' => 0,
1354
  'comments' => 0,
1355
  'blogroll' => 0,
1356
  ), $total);
1357
+
1358
  // Update scan URL status row
1359
  $this->update_scan_url_status($url_id, $scan_id, array('total_posts' => $total['posts'], 'total_comments' => $total['comments'], 'total_blogroll' => $total['blogroll']));
1360
  }
1365
  * Retrieve URL status info
1366
  */
1367
  public function get_scan_url_status($args = array()) {
1368
+
1369
  // Globals
1370
  global $wpdb;
1371
+
1372
  // Check arguments
1373
+ if (empty($args) || !is_array($args)) {
1374
  return false;
1375
+ }
1376
+
1377
  // Extract parameters
1378
  extract($args);
1379
+
1380
  // Cast arguments
1381
  $url_id = isset($url_id)? (int) $url_id : 0;
1382
  $scan_id = isset($scan_id)? (int) $scan_id : 0;
1383
  $status = isset($status)? $status : false;
1384
  $phase = isset($phase)? $phase : false;
1385
+
1386
  // Check identifiers
1387
+ if (empty($url_id) && empty($scan_id)) {
1388
  return false;
1389
+ }
1390
+
1391
  // Force cache for an isolated record
1392
+ if (!isset($no_cache) && !empty($url_id) && !empty($scan_id)) {
1393
  $no_cache = true;
1394
+ }
1395
+
1396
  // Initialize
1397
  $where = '1 = 1';
1398
+
1399
  // Check URL id
1400
+ if (!empty($url_id)) {
1401
  $where .= ' AND url_id = '.$url_id;
1402
+ }
1403
+
1404
  // Check scan id
1405
+ if (!empty($scan_id)) {
1406
  $where .= ' AND scan_id = '.$scan_id;
1407
+ }
1408
+
1409
  // Check status
1410
+ if (false !== $status) {
1411
  $where .= ' AND status = "'.esc_sql($status).'"';
1412
+ }
1413
+
1414
  // Check phase
1415
+ if (false !== $phase) {
1416
  $where .= ' AND phase'.(is_array($phase)? ' IN ("'.implode('", "', array_map('esc_sql', $phase)).'")' : ' = "'.esc_sql($phase).'"');
1417
+ }
1418
+
1419
  // Order
1420
  $order_by = '';
1421
  if (isset($order)) {
1425
  if (2 == count($order_item)) {
1426
  if (in_array($order_item[0], array('url_id', 'scan_id', 'status', 'created_at', 'started_at'))) {
1427
  $order_item[1] = strtoupper($order_item[1]);
1428
+ if ('ASC' == $order_item[1] || 'DESC' == $order_item[1]) {
1429
  $order_by .= (empty($order_by)? ' ORDER BY ' : $order_by.', ').$order_item[0].' '.$order_item[1];
1430
+ }
1431
  }
1432
  }
1433
  }
1434
  }
1435
+
1436
  // Limit
1437
  $limit = '';
1438
  if (isset($limit_rows)) {
1439
  $limit_rows = (int) $limit_rows;
1440
+ if (!empty($limit_rows)) {
1441
  $limit = ' LIMIT '.(isset($limit_base)? (int) $limit_base.', ' : '').$limit_rows;
1442
+ }
1443
  }
1444
+
1445
  // Perform query
1446
  $rows = $wpdb->get_results('SELECT '.(isset($no_cache)? 'SQL_NO_CACHE ' : '').'* FROM '.$wpdb->prefix.'wplnst_urls_status WHERE '.$where.$order_by.$limit);
1447
+
1448
  // Done
1449
  return (empty($rows) || !is_array($rows))? false : $rows;
1450
  }
1455
  * New URL status record
1456
  */
1457
  public function new_scan_url_status($url_id, $scan_id, $insert) {
1458
+
1459
  // Globals
1460
  global $wpdb;
1461
+
1462
  // Add new scan status
1463
  return $wpdb->query($wpdb->prepare('INSERT IGNORE INTO '.$wpdb->prefix.'wplnst_urls_status SET url_id = %d, scan_id = %d, phase = %s, created_at = %s', $url_id, $scan_id, $phase, current_time('mysql', true)));
1464
  }
1469
  * Insert new URL status record
1470
  */
1471
  public function add_scan_url_status($url_id, $scan_id, $phase) {
1472
+
1473
  // Globals
1474
  global $wpdb;
1475
+
1476
  // Add new scan status
1477
  return $wpdb->query($wpdb->prepare('INSERT IGNORE INTO '.$wpdb->prefix.'wplnst_urls_status SET url_id = %d, scan_id = %d, phase = %s, created_at = %s', $url_id, $scan_id, $phase, current_time('mysql', true)));
1478
  }
1483
  * Update a URL status phase
1484
  */
1485
  public function update_scan_url_status($url_id, $scan_id, $update) {
1486
+
1487
  // Globals
1488
  global $wpdb;
1489
+
1490
  // Update play value
1491
  return $wpdb->update($wpdb->prefix.'wplnst_urls_status', $update, array('url_id' => $url_id, 'scan_id' => $scan_id));
1492
  }
1497
  * Remove URL status record
1498
  */
1499
  public function remove_scan_url_status($url_id, $scan_id) {
1500
+
1501
  // Globals
1502
  global $wpdb;
1503
+
1504
  // Remove record
1505
  return $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_status WHERE url_id = %d AND scan_id = %d LIMIT 1', $url_id, $scan_id));
1506
  }
1511
  * Remove discard URL status and locations
1512
  */
1513
  public function remove_scan_discard_urls($scan_id) {
1514
+
1515
  // Globals
1516
  global $wpdb;
1517
+
1518
  // Remove locations
1519
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE scan_id = %d AND url_id IN (SELECT url_id FROM '.$wpdb->prefix.'wplnst_urls_status WHERE scan_id = %d AND phase = "discard")', $scan_id, $scan_id));
1520
+
1521
  // Remove URL status
1522
  $wpdb->query($wpdb->prepare('DELETE FROM '.$wpdb->prefix.'wplnst_urls_status WHERE scan_id = %d AND phase = "discard"', $scan_id));
1523
  }
1533
  * Retrieve URL request headers
1534
  */
1535
  public function get_scan_result_headers($scan_id, $url_id) {
1536
+
1537
  // Globals
1538
  global $wpdb;
1539
+
1540
  // Retrieve headers
1541
  return $wpdb->get_row($wpdb->prepare('SELECT headers, headers_request, request_at, total_time, total_bytes FROM '.$wpdb->prefix.'wplnst_urls_status WHERE url_id = %d AND scan_id = %d', $url_id, $scan_id));
1542
  }
1547
  * Retrieve scan results
1548
  */
1549
  public function get_scan_results($args) {
1550
+
1551
  // Globals
1552
  global $wpdb;
1553
+
1554
  // Check arguments
1555
+ if (empty($args) || !is_array($args)) {
1556
  return false;
1557
+ }
1558
+
1559
  // Extract parameters
1560
  extract($args);
1561
+
1562
  // Check scan id
1563
  $scan_id = empty($scan_id)? 0 : (int) $scan_id;
1564
+ if (empty($scan_id)) {
1565
  return false;
1566
+ }
1567
+
1568
  // Check page
1569
  $paged = empty($paged)? 1 : (int) $paged;
1570
+ if (empty($paged)) {
1571
  $paged = 1;
1572
+ }
1573
+
1574
  // Check elements per page
1575
  $per_page = isset($per_page)? (int) $per_page : (int) get_user_option('wplnst_scan_results_per_page');
1576
+ if (empty($per_page)) {
1577
  $per_page = WPLNST_Core_Types::scans_results_per_page;
1578
+ }
1579
+
1580
  // Prepare fields
1581
  $fields = 'u.url_id, u.url, u.scheme, u.host, u.scope,';
1582
  $fields .= 's.status_level, s.status_code, s.curl_errno, s.phase, s.redirect_url, s.redirect_steps, s.redirect_url_id, s.redirect_url_status, s.redirect_curl_errno, s.total_posts, s.total_comments, s.total_blogroll, s.total_time, s.total_bytes, s.rechecked, s.requests,';
1583
  $fields .= 'l.loc_id, l.link_type, l.object_id, l.object_type, l.object_field, l.detected_at, l.anchor, l.raw_url, l.fragment, l.spaced, l.malformed, l.absolute, l.protorel, l.relative, l.nofollow, l.ignored, l.unlinked, l.modified, l.anchored, l.attributed';
1584
+
1585
  // Prepare inner join
1586
  $inner_join = ' INNER JOIN '.$wpdb->prefix.'wplnst_urls_status s ON u.url_id = s.url_id ';
1587
+
1588
  // Prepare right join
1589
  $right_join = ' RIGHT JOIN '.$wpdb->prefix.'wplnst_urls_locations l ON s.url_id = l.url_id AND s.scan_id = l.scan_id';
1590
+
1591
  /* Prepare where */
1592
+
1593
  // Base conditions
1594
  $where = 's.scan_id = '.$scan_id.' AND u.url_id = s.url_id AND s.phase = "end"';
1595
+
1596
  // Check URL id
1597
  if (!empty($url_id)) {
1598
  $where .= ' AND u.url_id = '.((int) $url_id);
1599
+
1600
  // Check status level
1601
  } elseif (isset($status_level) && false !== $status_level) {
1602
  $where .= ' AND s.status_level = "'.esc_sql($status_level).'"';
1603
+
1604
  // Check status code
1605
  } elseif (isset($status_code) && false !== $status_code) {
1606
  $where .= ' AND s.status_code = "'.esc_sql($status_code).'"';
1607
  }
1608
+
1609
  // Check object type
1610
+ if (isset($object_type) && false !== $object_type) {
1611
  $where .= ' AND l.object_type = "'.esc_sql($object_type).'"';
1612
+ }
1613
+
1614
  // Check object post type
1615
+ if (isset($object_post_type) && false !== $object_post_type) {
1616
+ $where .= ' AND l.object_post_type = "'.esc_sql($object_post_type).'"';
1617
+ }
1618
+
1619
  // Check link type
1620
+ if (isset($link_type) && false !== $link_type) {
1621
  $where .= ' AND l.link_type = "'.esc_sql($link_type).'"';
1622
+ }
1623
+
1624
  // Check ignored type
1625
  if (isset($ignored_type) && false !== $ignored_type) {
1626
+ if ('oir' == $ignored_type) {
1627
  $where .= ' AND l.ignored = 1';
1628
+ }
1629
  } else {
1630
  $where .= ' AND l.ignored = 0';
1631
  }
1632
+
1633
  // SEO link type
1634
+ if (isset($seo_link_type) && false !== $seo_link_type) {
1635
  $where .= ' AND l.nofollow = '.(('nf' == $seo_link_type)? '1' : '0');
1636
+ }
1637
+
1638
  // Protocol type
1639
+ if (isset($protocol_type) && false !== $protocol_type) {
1640
  $where .= ('rel' == $protocol_type)? ' AND l.protorel = 1' : ' AND u.scheme = "'.esc_sql($protocol_type).'" AND l.protorel = 0';
1641
+ }
1642
+
1643
  // Special type
1644
  if (isset($special_type) && false !== $special_type) {
1645
  if ('rel' == $special_type) {
1652
  $where .= ' AND l.malformed = 1';
1653
  }
1654
  }
1655
+
1656
  // Action type
1657
  if (isset($action_type) && false !== $action_type) {
1658
  if ('unl' == $action_type) {
1665
  $where .= ' AND s.rechecked = 1';
1666
  }
1667
  }
1668
+
1669
  // Check destination type
1670
+ if (isset($dest_type) && false !== $dest_type && 'all' != $dest_type) {
1671
  $where .= ' AND u.scope = "'.esc_sql($dest_type).'"';
1672
+ }
1673
+
1674
  // Check search URL
1675
  if (isset($search_url) && false !== $search_url && '' !== $search_url) {
1676
  $like = esc_sql(addcslashes($search_url, '_%\\'));
1681
  $where .= ' AND (u.url'.$op.' OR s.redirect_url'.$op.')';
1682
  }
1683
  }
1684
+
1685
  // Check search anchor
1686
  if (isset($search_anchor) && false !== $search_anchor && '' !== $search_anchor) {
1687
  $op = ('f' == $search_anchor_type)? ' = "'.esc_sql($search_anchor).'"' : ' LIKE "'.(('s' == $search_anchor_type || 'm' == $search_anchor_type)? '%' : '').esc_sql(addcslashes($search_anchor, '_%\\')).(('p' == $search_anchor_type || 'm' == $search_anchor_type)? '%' : '').'"';
1688
  $where .= ' AND l.anchor'.$op;
1689
  }
1690
+
1691
  // Check first order by date
1692
  if (isset($order_type) && false !== $order_type) {
1693
+
1694
  // Change default order
1695
  if (in_array($order_type, array_keys(WPLNST_Core_Types::get_crawl_order()))) {
1696
  $order_by = 'l.object_date_gmt '.(('asc' == $order_type)? 'ASC' : 'DESC');
1697
+
1698
  // Orders
1699
  } else {
1700
  if ('dma' == $order_type) {
1711
  $order_by = 's.total_bytes DESC';
1712
  }
1713
  }
1714
+
1715
  // Default order
1716
  } else {
1717
  $order_date = (isset($order_date) && in_array(strtoupper($order_date), array('ASC', 'DESC')))? strtoupper($order_date) : 'DESC';
1718
  $order_by = 'l.object_date_gmt '.$order_date;
1719
  }
1720
+
1721
+
1722
  // Done
1723
  return $this->pagination(array(
1724
  'paged' => $paged,
1737
  * Retrieve scan locations
1738
  */
1739
  public function get_scan_locations($args) {
1740
+
1741
  // Globals
1742
  global $wpdb;
1743
+
1744
  // Check arguments
1745
+ if (empty($args) || !is_array($args)) {
1746
  return false;
1747
+ }
1748
+
1749
  // Extract parameters
1750
  extract($args);
1751
+
1752
  // Check scan id
1753
  $scan_id = empty($scan_id)? false : (int) $scan_id;
1754
+ if (empty($scan_id)) {
1755
  return false;
1756
+ }
1757
+
1758
  // Check url id
1759
  $url_id = empty($url_id)? false : (is_array($url_id)? array_map('intval', $url_id) : (int) $url_id);
1760
+ if (empty($url_id)) {
1761
  return false;
1762
+ }
1763
+
1764
  // URL id where
1765
  $url_id_where = is_array($url_id)? ' IN ('.implode(', ', $url_id).')' : ' = '.$url_id;
1766
+
1767
  // Others
1768
  $where = '';
1769
+
1770
  // Check object type
1771
+ if (!empty($object_type)) {
1772
  $where .= ' AND object_type = "'.esc_sql($object_type).'"';
1773
+ }
1774
+
1775
  // Check page
1776
  $paged = empty($paged)? 1 : (int) $paged;
1777
+ if (empty($paged)) {
1778
  $paged = 1;
1779
+ }
1780
+
1781
  // Check elements per page
1782
  $per_page = isset($per_page)? (int) $per_page : (int) get_user_option('wplnst_scan_locations_per_page');
1783
+ if (empty($per_page)) {
1784
  $per_page = 25;
1785
+ }
1786
+
1787
  // Done
1788
  return $this->pagination(array(
1789
  'paged' => $paged,
1802
  * Retrieve single scan location
1803
  */
1804
  public function get_scan_location_by_id($loc_id) {
1805
+
1806
  // Global
1807
  global $wpdb;
1808
+
1809
  // Cast param
1810
  $loc_id = (int) $loc_id;
1811
+
1812
  // Perform query and return result
1813
  $locations = $wpdb->get_results($wpdb->prepare('SELECT * FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE loc_id = %d', $loc_id));
1814
  return (!empty($locations) && is_array($locations) && 1 == count($locations))? $locations[0] : false;
1820
  * Retrieve multiple scan locations
1821
  */
1822
  public function get_scan_locations_by_ids($loc_ids) {
1823
+
1824
  // Global
1825
  global $wpdb;
1826
+
1827
  // Perform query and return result
1828
  $locations = $wpdb->get_results('SELECT * FROM '.$wpdb->prefix.'wplnst_urls_locations WHERE loc_id IN ('.implode(', ', array_map('intval', $loc_ids)).')');
1829
  return (empty($locations) || !is_array($locations))? false : $locations;
1835
  * Retrieve array info of location marks
1836
  */
1837
  public function get_scan_location_marks($scan_id, $loc_id) {
1838
+
1839
  // Global
1840
  global $wpdb;
1841
+
1842
  // Default
1843
  $marks = array(
1844
  'url' => '',
1851
  'redirs' => false,
1852
  'redirs_count' => '1 redirect',
1853
  );
1854
+
1855
  // Retrieve row
1856
  $row = $wpdb->get_row($wpdb->prepare('SELECT u.url, u.scheme, l.relative, l.absolute, l.spaced, l.malformed, l.protorel, s.status_level, s.redirect_url_id, s.redirect_url, s.redirect_steps FROM '.$wpdb->prefix.'wplnst_urls AS u, '.$wpdb->prefix.'wplnst_urls_locations AS l, '.$wpdb->prefix.'wplnst_urls_status AS s WHERE l.loc_id = %d AND l.scan_id = %d AND u.url_id = l.url_id AND s.url_id = l.url_id AND s.scan_id = %d LIMIT 1', $loc_id, $scan_id, $scan_id));
1857
  if (!empty($row) && is_object($row)) {
1858
+
1859
  // Copy URL
1860
  $marks['url'] = esc_html($row->url);
1861
+
1862
  // Check HTTPS
1863
  $marks['https'] = ('https' == $row->scheme);
1864
+
1865
  // Link form
1866
  $marks['relative'] = (1 == $row->relative);
1867
  $marks['absolute'] = (1 == $row->absolute);
1868
  $marks['spaced'] = (1 == $row->spaced);
1869
  $marks['malformed'] = (1 == $row->malformed);
1870
  $marks['protorel'] = (1 == $row->protorel);
1871
+
1872
  // Redirs
1873
  $marks['redirs'] = ('3' == $row->status_level && $row->redirect_url_id > 0 && !empty($row->redirect_url));
1874
  if ($marks['redirs']) {
1875
  $redirs_steps = @json_decode($row->redirect_steps, true);
1876
+ if (!empty($redirs_steps) && is_array($redirs_steps) && count($redirs_steps) > 1) {
1877
  $marks['redirs_count'] = count($redirs_steps).' redirects';
1878
+ }
1879
  }
1880
  }
1881
+
1882
  // Done
1883
  return $marks;
1884
  }
1896
  * - no_cache
1897
  */
1898
  public function pagination($args) {
1899
+
1900
  // Globals
1901
  global $wpdb;
1902
+
1903
  // Check arguments
1904
+ if (empty($args) || !is_array($args)) {
1905
  return false;
1906
+ }
1907
+
1908
  // Extract parameters
1909
  extract($args);
1910
+
1911
  // Check basic params
1912
+ if (empty($sql) || empty($fields)) {
1913
  return false;
1914
+ }
1915
+
1916
  // Totals method and cache
1917
  $calc_rows = !empty($calc_rows) && (true === $calc_rows);
1918
  $no_cache = !empty($no_cache) && (true === $no_cache);
1919
+
1920
  // Calculating offset
1921
  $paged = empty($paged)? 1 : (int) $paged;
1922
  $per_page = empty($per_page)? 10 : (int) $per_page;
1923
  $offset = (int) (($paged - 1) * $per_page);
1924
+
1925
  // Default
1926
  $results = array(
1927
  'paged' => $paged,
1935
  'no_cache' => $no_cache,
1936
  'rows' => array(),
1937
  );
1938
+
1939
  // Timer
1940
  $time_start = microtime(true);
1941
+
1942
  // Count rows method
1943
  if (!$calc_rows) {
1944
+
1945
  // Prepare COUNT sql
1946
  $sql_count = str_replace('$$$fields$$$', 'COUNT(*)', $sql);
1947
+ if ($no_cache) {
1948
  $sql_count = str_replace('SELECT ', 'SELECT SQL_NO_CACHE ', $sql_count);
1949
+ }
1950
+
1951
  // Obtain totals
1952
  $results['total_rows'] = (int) $wpdb->get_var($sql_count);
1953
+
1954
  // Calc
1955
  } else {
1956
+
1957
+ // Replace SELECT
1958
  $sql = str_replace('SELECT ', 'SELECT SQL_CALC_FOUND_ROWS ', $sql);
1959
  }
1960
+
1961
  // Check NO CACHE
1962
+ if ($no_cache) {
1963
  $sql = str_replace('SELECT ', 'SELECT SQL_NO_CACHE ', $sql);
1964
+ }
1965
+
1966
  // Set fields
1967
  $sql = str_replace('$$$fields$$$', $fields, $sql);
1968
+
1969
  // Add ORDER and LIMIT
1970
  $sql .= (empty($order_by)? '' : ' ORDER BY '.$order_by).' LIMIT '.$offset.', '.$per_page;
1971
  //echo $sql;
1972
  // Perform query
1973
  $results['rows'] = $wpdb->get_results($sql);
1974
+
1975
  // Calc rows
1976
+ if ($calc_rows) {
1977
  $results['total_rows'] = (int) $wpdb->get_var('SELECT FOUND_ROWS()');
1978
+ }
1979
+
1980
  // End timer
1981
  $results['time'] = microtime(true) - $time_start;
1982
  //echo '<br />'.$results['time'].' s';
1983
  // Total pages
1984
  $results['total_pages'] = empty($results['total_rows'])? 0 : ceil($results['total_rows'] / $per_page);
1985
+
1986
  // Queried rows
1987
  if (!empty($results['rows']) && is_array($results['rows'])) {
1988
+
1989
  // Total rows in page
1990
  $results['rows_page'] = count($results['rows']);
1991
  $results['rows_end'] = $results['rows_start'] + $results['rows_page'] - 1;
1992
  }
1993
+
1994
  // Done
1995
  return (object) $results;
1996
  }
core/scheme.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Scheme class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Scheme {
10
 
@@ -30,16 +30,17 @@ class WPLNST_Core_Scheme {
30
  * Remove all plugin tables
31
  */
32
  public static function drop_tables() {
33
-
34
  // Globals
35
  global $wpdb;
36
-
37
  // Plugin tables
38
  $tables = self::get_tables();
39
-
40
  // Remove each one
41
- foreach ($tables as $name)
42
  $wpdb->query('DROP TABLE '.$wpdb->prefix.'wplnst_'.esc_sql($name));
 
43
  }
44
 
45
 
@@ -48,23 +49,24 @@ class WPLNST_Core_Scheme {
48
  * Check plugin custom tables
49
  */
50
  public static function check_tables() {
51
-
52
  // Globals
53
  global $wpdb;
54
-
55
  // Initialize
56
  $create = array();
57
-
58
  // Plugin tables
59
  $tables = self::get_tables();
60
-
61
  // Check each table
62
  foreach ($tables as $name) {
63
  $result = $wpdb->get_var('SHOW TABLES LIKE "'.$wpdb->prefix.'wplnst_'.esc_sql($name).'"');
64
- if (empty($result))
65
  $create[] = $name;
 
66
  }
67
-
68
  // Done
69
  return empty($create)? false : $create;
70
  }
@@ -75,13 +77,13 @@ class WPLNST_Core_Scheme {
75
  * Create custom plugin tables
76
  */
77
  public static function create_tables($tables = array()) {
78
-
79
  // Globals
80
  global $wpdb;
81
-
82
  // Compose charset
83
  $charset = (empty($wpdb->charset)? '' : ' DEFAULT CHARACTER SET '.$wpdb->charset).(empty($wpdb->collate)? '' : ' COLLATE '.$wpdb->collate);
84
-
85
  // URLs table
86
  if (in_array('urls', $tables)) {
87
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_urls` (
@@ -114,7 +116,7 @@ class WPLNST_Core_Scheme {
114
  KEY `last_request_at` (`last_request_at`)
115
  )'.$charset);
116
  }
117
-
118
  // URLs and locations relationship table
119
  if (in_array('urls_locations', $tables)) {
120
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_urls_locations` (
@@ -164,7 +166,7 @@ class WPLNST_Core_Scheme {
164
  KEY `attributed` (`attributed`)
165
  )'.$charset);
166
  }
167
-
168
  // URLs locations and attributes relationship table
169
  if (in_array('urls_locations_att', $tables)) {
170
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_urls_locations_att` (
@@ -180,7 +182,7 @@ class WPLNST_Core_Scheme {
180
  KEY `value` (`value`)
181
  )'.$charset);
182
  }
183
-
184
  // URLs status and scans relationship table
185
  if (in_array('urls_status', $tables)) {
186
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_urls_status` (
@@ -227,7 +229,7 @@ class WPLNST_Core_Scheme {
227
  KEY `rechecked` (`rechecked`)
228
  )'.$charset);
229
  }
230
-
231
  // Scans table
232
  if (in_array('scans', $tables)) {
233
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_scans` (
@@ -260,7 +262,7 @@ class WPLNST_Core_Scheme {
260
  KEY `config` (`config`(255))
261
  )'.$charset);
262
  }
263
-
264
  // Scans objects
265
  if (in_array('scans_objects', $tables)) {
266
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_scans_objects` (
1
  <?php
2
 
3
  /**
4
+ * Scheme class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Scheme {
10
 
30
  * Remove all plugin tables
31
  */
32
  public static function drop_tables() {
33
+
34
  // Globals
35
  global $wpdb;
36
+
37
  // Plugin tables
38
  $tables = self::get_tables();
39
+
40
  // Remove each one
41
+ foreach ($tables as $name) {
42
  $wpdb->query('DROP TABLE '.$wpdb->prefix.'wplnst_'.esc_sql($name));
43
+ }
44
  }
45
 
46
 
49
  * Check plugin custom tables
50
  */
51
  public static function check_tables() {
52
+
53
  // Globals
54
  global $wpdb;
55
+
56
  // Initialize
57
  $create = array();
58
+
59
  // Plugin tables
60
  $tables = self::get_tables();
61
+
62
  // Check each table
63
  foreach ($tables as $name) {
64
  $result = $wpdb->get_var('SHOW TABLES LIKE "'.$wpdb->prefix.'wplnst_'.esc_sql($name).'"');
65
+ if (empty($result)) {
66
  $create[] = $name;
67
+ }
68
  }
69
+
70
  // Done
71
  return empty($create)? false : $create;
72
  }
77
  * Create custom plugin tables
78
  */
79
  public static function create_tables($tables = array()) {
80
+
81
  // Globals
82
  global $wpdb;
83
+
84
  // Compose charset
85
  $charset = (empty($wpdb->charset)? '' : ' DEFAULT CHARACTER SET '.$wpdb->charset).(empty($wpdb->collate)? '' : ' COLLATE '.$wpdb->collate);
86
+
87
  // URLs table
88
  if (in_array('urls', $tables)) {
89
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_urls` (
116
  KEY `last_request_at` (`last_request_at`)
117
  )'.$charset);
118
  }
119
+
120
  // URLs and locations relationship table
121
  if (in_array('urls_locations', $tables)) {
122
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_urls_locations` (
166
  KEY `attributed` (`attributed`)
167
  )'.$charset);
168
  }
169
+
170
  // URLs locations and attributes relationship table
171
  if (in_array('urls_locations_att', $tables)) {
172
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_urls_locations_att` (
182
  KEY `value` (`value`)
183
  )'.$charset);
184
  }
185
+
186
  // URLs status and scans relationship table
187
  if (in_array('urls_status', $tables)) {
188
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_urls_status` (
229
  KEY `rechecked` (`rechecked`)
230
  )'.$charset);
231
  }
232
+
233
  // Scans table
234
  if (in_array('scans', $tables)) {
235
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_scans` (
262
  KEY `config` (`config`(255))
263
  )'.$charset);
264
  }
265
+
266
  // Scans objects
267
  if (in_array('scans_objects', $tables)) {
268
  $wpdb->query('CREATE TABLE IF NOT EXISTS `'.$wpdb->prefix.'wplnst_scans_objects` (
core/settings.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Settings class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Settings {
10
 
@@ -14,25 +14,29 @@ class WPLNST_Core_Settings {
14
  * Return a numeric setting
15
  */
16
  public static function get_nsetting($name, $value = 0) {
17
-
18
  // Load settings
19
  static $settings;
20
- if (!isset($settings))
21
  $settings = self::get_default_nsettings();
22
-
 
23
  // Check available
24
- if (!isset($settings[$name]))
25
  return false;
26
-
 
27
  // Check boundary
28
- if ('min' === $value || 'max' === $value)
29
  return $settings[$name][$value];
30
-
 
31
  // Check input value
32
  $value = (int) $value;
33
- if (empty($value))
34
  $value = (int) get_option('wplnst_'.$name);
35
-
 
36
  // Check return value
37
  $setting = $settings[$name];
38
  return (empty($value) || $value < $setting['min'] || $value > $setting['max'])? $setting['default'] : $value;
@@ -69,17 +73,19 @@ class WPLNST_Core_Settings {
69
  * Return a boolean setting
70
  */
71
  public static function get_bsetting($name, $use_default_if_empty = true) {
72
-
73
  // Check stored value
74
  $value = ''.get_option('wplnst_'.$name);
75
- if ('' !== $value || !$use_default_if_empty)
76
  return ('on' == $value);
77
-
 
78
  // Load settings
79
  static $settings;
80
- if (!isset($settings))
81
  $settings = self::get_default_bsettings();
82
-
 
83
  // Return default setting or false
84
  return isset($settings[$name])? ('on' == $settings[$name]) : false;
85
  }
@@ -102,17 +108,19 @@ class WPLNST_Core_Settings {
102
  * Return a text setting
103
  */
104
  public static function get_tsetting($name, $use_default_if_empty = true) {
105
-
106
  // Check stored value
107
  $value = ''.get_option('wplnst_'.$name);
108
- if ('' !== $value || !$use_default_if_empty)
109
  return $value;
110
-
 
111
  // Load settings
112
  static $settings;
113
- if (!isset($settings))
114
  $settings = self::get_default_tsettings();
115
-
 
116
  // Return default setting or false
117
  return isset($settings[$name])? $settings[$name] : false;
118
  }
@@ -134,7 +142,7 @@ class WPLNST_Core_Settings {
134
  * Remove all plugin options
135
  */
136
  public static function delete_all_options() {
137
-
138
  // Collect numeric, text, and crawler options
139
  $options = array_merge(
140
  array_keys(self::get_default_nsettings()),
@@ -142,10 +150,11 @@ class WPLNST_Core_Settings {
142
  array_keys(self::get_default_bsettings()),
143
  self::get_crawler_options_names()
144
  );
145
-
146
  // Remove all plugin settings
147
- foreach ($options as $name)
148
  delete_option('wplnst_'.$name);
 
149
  }
150
 
151
 
@@ -155,8 +164,9 @@ class WPLNST_Core_Settings {
155
  */
156
  public static function delete_crawler_options() {
157
  $options = self::get_crawler_options_names();
158
- foreach ($options as $name)
159
- delete_option('wplnst_'.$name);
 
160
  }
161
 
162
 
1
  <?php
2
 
3
  /**
4
+ * Settings class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Settings {
10
 
14
  * Return a numeric setting
15
  */
16
  public static function get_nsetting($name, $value = 0) {
17
+
18
  // Load settings
19
  static $settings;
20
+ if (!isset($settings)) {
21
  $settings = self::get_default_nsettings();
22
+ }
23
+
24
  // Check available
25
+ if (!isset($settings[$name])) {
26
  return false;
27
+ }
28
+
29
  // Check boundary
30
+ if ('min' === $value || 'max' === $value) {
31
  return $settings[$name][$value];
32
+ }
33
+
34
  // Check input value
35
  $value = (int) $value;
36
+ if (empty($value)) {
37
  $value = (int) get_option('wplnst_'.$name);
38
+ }
39
+
40
  // Check return value
41
  $setting = $settings[$name];
42
  return (empty($value) || $value < $setting['min'] || $value > $setting['max'])? $setting['default'] : $value;
73
  * Return a boolean setting
74
  */
75
  public static function get_bsetting($name, $use_default_if_empty = true) {
76
+
77
  // Check stored value
78
  $value = ''.get_option('wplnst_'.$name);
79
+ if ('' !== $value || !$use_default_if_empty) {
80
  return ('on' == $value);
81
+ }
82
+
83
  // Load settings
84
  static $settings;
85
+ if (!isset($settings)) {
86
  $settings = self::get_default_bsettings();
87
+ }
88
+
89
  // Return default setting or false
90
  return isset($settings[$name])? ('on' == $settings[$name]) : false;
91
  }
108
  * Return a text setting
109
  */
110
  public static function get_tsetting($name, $use_default_if_empty = true) {
111
+
112
  // Check stored value
113
  $value = ''.get_option('wplnst_'.$name);
114
+ if ('' !== $value || !$use_default_if_empty) {
115
  return $value;
116
+ }
117
+
118
  // Load settings
119
  static $settings;
120
+ if (!isset($settings)) {
121
  $settings = self::get_default_tsettings();
122
+ }
123
+
124
  // Return default setting or false
125
  return isset($settings[$name])? $settings[$name] : false;
126
  }
142
  * Remove all plugin options
143
  */
144
  public static function delete_all_options() {
145
+
146
  // Collect numeric, text, and crawler options
147
  $options = array_merge(
148
  array_keys(self::get_default_nsettings()),
150
  array_keys(self::get_default_bsettings()),
151
  self::get_crawler_options_names()
152
  );
153
+
154
  // Remove all plugin settings
155
+ foreach ($options as $name) {
156
  delete_option('wplnst_'.$name);
157
+ }
158
  }
159
 
160
 
164
  */
165
  public static function delete_crawler_options() {
166
  $options = self::get_crawler_options_names();
167
+ foreach ($options as $name) {
168
+ delete_option('wplnst_'.$name);
169
+ }
170
  }
171
 
172
 
core/status.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Status class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Status {
10
 
@@ -96,8 +96,9 @@ class WPLNST_Core_Status {
96
  * Constructor
97
  */
98
  public function __construct($data = null) {
99
- if (!empty($data) && is_array($data))
100
  $this->process_data($data);
 
101
  }
102
 
103
 
@@ -111,36 +112,42 @@ class WPLNST_Core_Status {
111
  * Process request data
112
  */
113
  public function process_data($data) {
114
-
115
  // Copy var
116
  $this->data = $data;
117
-
118
  // Process headers
119
- if (!empty($data['headers']))
120
  $this->extract_headers($data['headers']);
121
-
 
122
  // Process request headers
123
- if (!empty($data['headers_request']))
124
  $this->extract_headers_request($data['headers_request']);
125
-
 
126
  // Check cURL error
127
- if (!empty($data['curl_errno']))
128
  $this->curl_errno = (int) $data['curl_errno'];
129
-
 
130
  // Timestamp and DateTime
131
  if (!empty($data['timestamp'])) {
132
  $this->timestamp = (int) $data['timestamp'];
133
- if (!empty($this->timestamp) && false !== ($datetime = @gmdate('Y-m-d H:i:s', $this->timestamp)))
134
  $this->request_at = $datetime;
 
135
  }
136
-
137
  // Total time
138
- if (!empty($data['total_time']))
139
  $this->total_time = (float) $data['total_time'];
140
-
 
141
  // Total bytes
142
- if (!empty($data['total_bytes']))
143
  $this->total_bytes = (int) $data['total_bytes'];
 
144
  }
145
 
146
 
@@ -149,16 +156,17 @@ class WPLNST_Core_Status {
149
  * Parse and extract headers data
150
  */
151
  private function extract_headers($headers) {
152
-
153
  // Parse headers
154
  $headers_raw = explode("\n", str_replace("\n\r", "\n", $headers));
155
  foreach ($headers_raw as $header) {
156
-
157
  // Clean line
158
  $header = trim($header);
159
- if (empty($header))
160
  continue;
161
-
 
162
  // Check redirection in status code
163
  if (!isset($status_code) && 0 === stripos($header, 'HTTP/')) {
164
  $line = trim(preg_replace('/\s+/', ' ', $header));
@@ -167,16 +175,17 @@ class WPLNST_Core_Status {
167
  $status_code = (int) mb_substr(trim($line[1]), 0, 3);
168
  $this->headers['status'] = $header;
169
  }
170
-
171
  // Parse other headers
172
  } elseif (false !== ($pos = strpos($header, ':')) && $pos > 0) {
173
  $name = trim(mb_substr($header, 0, $pos));
174
  $this->headers[$name] = trim(mb_substr($header, $pos + 1));
175
- if ('location' == strtolower($name))
176
  $this->redirect_url = $this->headers[$name];
 
177
  }
178
  }
179
-
180
  // Check status
181
  if (isset($status_code)) {
182
  $this->code = $status_code;
@@ -190,15 +199,15 @@ class WPLNST_Core_Status {
190
  * Parse and extract request headers data
191
  */
192
  private function extract_headers_request($headers) {
193
-
194
  // Parse headers
195
  $headers_raw = explode("\n", str_replace("\n\r", "\n", $headers));
196
  foreach ($headers_raw as $header) {
197
-
198
  // Check GET method
199
  if (0 === strpos($header, 'GET ')) {
200
  $this->headers_request['GET'] = mb_substr($header, 4);
201
-
202
  // Check property
203
  } elseif ((false !== ($pos = strpos($header, ':')) && $pos > 0)) {
204
  $name = trim(mb_substr($header, 0, $pos));
1
  <?php
2
 
3
  /**
4
+ * Status class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Status {
10
 
96
  * Constructor
97
  */
98
  public function __construct($data = null) {
99
+ if (!empty($data) && is_array($data)) {
100
  $this->process_data($data);
101
+ }
102
  }
103
 
104
 
112
  * Process request data
113
  */
114
  public function process_data($data) {
115
+
116
  // Copy var
117
  $this->data = $data;
118
+
119
  // Process headers
120
+ if (!empty($data['headers'])) {
121
  $this->extract_headers($data['headers']);
122
+ }
123
+
124
  // Process request headers
125
+ if (!empty($data['headers_request'])) {
126
  $this->extract_headers_request($data['headers_request']);
127
+ }
128
+
129
  // Check cURL error
130
+ if (!empty($data['curl_errno'])) {
131
  $this->curl_errno = (int) $data['curl_errno'];
132
+ }
133
+
134
  // Timestamp and DateTime
135
  if (!empty($data['timestamp'])) {
136
  $this->timestamp = (int) $data['timestamp'];
137
+ if (!empty($this->timestamp) && false !== ($datetime = @gmdate('Y-m-d H:i:s', $this->timestamp))) {
138
  $this->request_at = $datetime;
139
+ }
140
  }
141
+
142
  // Total time
143
+ if (!empty($data['total_time'])) {
144
  $this->total_time = (float) $data['total_time'];
145
+ }
146
+
147
  // Total bytes
148
+ if (!empty($data['total_bytes'])) {
149
  $this->total_bytes = (int) $data['total_bytes'];
150
+ }
151
  }
152
 
153
 
156
  * Parse and extract headers data
157
  */
158
  private function extract_headers($headers) {
159
+
160
  // Parse headers
161
  $headers_raw = explode("\n", str_replace("\n\r", "\n", $headers));
162
  foreach ($headers_raw as $header) {
163
+
164
  // Clean line
165
  $header = trim($header);
166
+ if (empty($header)) {
167
  continue;
168
+ }
169
+
170
  // Check redirection in status code
171
  if (!isset($status_code) && 0 === stripos($header, 'HTTP/')) {
172
  $line = trim(preg_replace('/\s+/', ' ', $header));
175
  $status_code = (int) mb_substr(trim($line[1]), 0, 3);
176
  $this->headers['status'] = $header;
177
  }
178
+
179
  // Parse other headers
180
  } elseif (false !== ($pos = strpos($header, ':')) && $pos > 0) {
181
  $name = trim(mb_substr($header, 0, $pos));
182
  $this->headers[$name] = trim(mb_substr($header, $pos + 1));
183
+ if ('location' == strtolower($name)) {
184
  $this->redirect_url = $this->headers[$name];
185
+ }
186
  }
187
  }
188
+
189
  // Check status
190
  if (isset($status_code)) {
191
  $this->code = $status_code;
199
  * Parse and extract request headers data
200
  */
201
  private function extract_headers_request($headers) {
202
+
203
  // Parse headers
204
  $headers_raw = explode("\n", str_replace("\n\r", "\n", $headers));
205
  foreach ($headers_raw as $header) {
206
+
207
  // Check GET method
208
  if (0 === strpos($header, 'GET ')) {
209
  $this->headers_request['GET'] = mb_substr($header, 4);
210
+
211
  // Check property
212
  } elseif ((false !== ($pos = strpos($header, ':')) && $pos > 0)) {
213
  $name = trim(mb_substr($header, 0, $pos));
core/text.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Text class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Text {
10
 
@@ -14,88 +14,89 @@ class WPLNST_Core_Text {
14
  * Translate on the fly (not stored) by name
15
  */
16
  public static function get_text($name) {
17
-
18
  // Static
19
  static $names = array();
20
-
21
  // Check cache
22
- if (isset($names[$name]))
23
  return $names[$name];
24
-
 
25
  // Initialize
26
  $text = false;
27
-
28
  // Check key
29
  switch($name) {
30
-
31
  case 'scans':
32
  $text = __('Scans', 'wplnst');
33
  break;
34
-
35
  case 'scan_new':
36
  $text = __('New scan', 'wplnst');
37
  break;
38
-
39
  case 'scan_new_add':
40
  $text = __('Add new scan', 'wplnst');
41
  break;
42
-
43
  case 'scan_edit':
44
  $text = __('Edit scan', 'wplnst');
45
  break;
46
-
47
  case 'scan_delete':
48
  $text = __('Delete scan', 'wplnst');
49
  break;
50
-
51
  case 'scan_delete_confirm':
52
  $text = __('Do you want to remove this scan?', 'wplnst');
53
  break;
54
-
55
  case 'crawler_action':
56
  $text = __('Crawler action', 'wplnst');
57
  break;
58
-
59
  case 'crawler_results':
60
  $text = __('Crawler results', 'wplnst');
61
  break;
62
-
63
  case 'settings':
64
  $text = __('Settings', 'wplnst');
65
  break;
66
-
67
  case 'max_scans':
68
  $text = sprintf(__('Sorry, maximum of <strong>%d running scans</strong> achieved and the scan has been enqueued, it will be launched as soon as possible.', 'wplnst'), wplnst_get_nsetting('max_scans'));
69
  break;
70
-
71
  case 'scan_not_found':
72
  $text = sprintf(__('Sorry, scan not found. Please go to the <a href="%s">scans list screen</a> and select another scan.', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans()));
73
  break;
74
-
75
  case 'invalid_data':
76
  $text = __('Sorry, <strong>invalid form data</strong>. Please, <a href="javascript:history.back();">go back</a>, reload the last page and try again.', 'wplnst');
77
  break;
78
-
79
  case 'invalid_nonce':
80
  $text = __('Sorry, <strong>invalid security data</strong>. Please, <a href="javascript:history.back();">go back</a>, reload the last page and try again.', 'wplnst');
81
  break;
82
-
83
  case 'server_comm_error':
84
  $text = __('Server communication error', 'wplnst');
85
  break;
86
-
87
  case 'unknown_error':
88
  $text = __('Unknown error', 'wplnst');
89
  break;
90
-
91
  case 'no_salt':
92
  $text = __('Unable to create the salt file needed to improve crawler security. Please check your <strong>wp content directory permissions</strong> allowing to save files.', 'wplnst');
93
  break;
94
  }
95
-
96
  // Save
97
  $names[$name] = $text;
98
-
99
  // Done
100
  return $text;
101
  }
1
  <?php
2
 
3
  /**
4
+ * Text class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Text {
10
 
14
  * Translate on the fly (not stored) by name
15
  */
16
  public static function get_text($name) {
17
+
18
  // Static
19
  static $names = array();
20
+
21
  // Check cache
22
+ if (isset($names[$name])) {
23
  return $names[$name];
24
+ }
25
+
26
  // Initialize
27
  $text = false;
28
+
29
  // Check key
30
  switch($name) {
31
+
32
  case 'scans':
33
  $text = __('Scans', 'wplnst');
34
  break;
35
+
36
  case 'scan_new':
37
  $text = __('New scan', 'wplnst');
38
  break;
39
+
40
  case 'scan_new_add':
41
  $text = __('Add new scan', 'wplnst');
42
  break;
43
+
44
  case 'scan_edit':
45
  $text = __('Edit scan', 'wplnst');
46
  break;
47
+
48
  case 'scan_delete':
49
  $text = __('Delete scan', 'wplnst');
50
  break;
51
+
52
  case 'scan_delete_confirm':
53
  $text = __('Do you want to remove this scan?', 'wplnst');
54
  break;
55
+
56
  case 'crawler_action':
57
  $text = __('Crawler action', 'wplnst');
58
  break;
59
+
60
  case 'crawler_results':
61
  $text = __('Crawler results', 'wplnst');
62
  break;
63
+
64
  case 'settings':
65
  $text = __('Settings', 'wplnst');
66
  break;
67
+
68
  case 'max_scans':
69
  $text = sprintf(__('Sorry, maximum of <strong>%d running scans</strong> achieved and the scan has been enqueued, it will be launched as soon as possible.', 'wplnst'), wplnst_get_nsetting('max_scans'));
70
  break;
71
+
72
  case 'scan_not_found':
73
  $text = sprintf(__('Sorry, scan not found. Please go to the <a href="%s">scans list screen</a> and select another scan.', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans()));
74
  break;
75
+
76
  case 'invalid_data':
77
  $text = __('Sorry, <strong>invalid form data</strong>. Please, <a href="javascript:history.back();">go back</a>, reload the last page and try again.', 'wplnst');
78
  break;
79
+
80
  case 'invalid_nonce':
81
  $text = __('Sorry, <strong>invalid security data</strong>. Please, <a href="javascript:history.back();">go back</a>, reload the last page and try again.', 'wplnst');
82
  break;
83
+
84
  case 'server_comm_error':
85
  $text = __('Server communication error', 'wplnst');
86
  break;
87
+
88
  case 'unknown_error':
89
  $text = __('Unknown error', 'wplnst');
90
  break;
91
+
92
  case 'no_salt':
93
  $text = __('Unable to create the salt file needed to improve crawler security. Please check your <strong>wp content directory permissions</strong> allowing to save files.', 'wplnst');
94
  break;
95
  }
96
+
97
  // Save
98
  $names[$name] = $text;
99
+
100
  // Done
101
  return $text;
102
  }
core/types-curl.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Types CURL class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Types_CURL {
10
 
@@ -22,11 +22,12 @@ class WPLNST_Core_Types_CURL {
22
 
23
  /**
24
  * Retrieve all error codes
25
- */
26
  public static function get_codes() {
27
  static $codes;
28
- if (!isset($codes))
29
  $codes = self::get_codes_array();
 
30
  return $codes;
31
  }
32
 
1
  <?php
2
 
3
  /**
4
+ * Types CURL class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Types_CURL {
10
 
22
 
23
  /**
24
  * Retrieve all error codes
25
+ */
26
  public static function get_codes() {
27
  static $codes;
28
+ if (!isset($codes)) {
29
  $codes = self::get_codes_array();
30
+ }
31
  return $codes;
32
  }
33
 
core/types.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Types class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_Types {
10
 
@@ -46,35 +46,38 @@ class WPLNST_Core_Types {
46
  * Post types allowed
47
  */
48
  public static function get_post_types($output = 'keys-names') {
49
-
50
  // Current avoid post types
51
  $avoid_post_types = apply_filters('wplnst_avoid_post_types', array_map('trim', explode(',', self::post_types_avoid)));
52
- if (empty($avoid_post_types) || !is_array($avoid_post_types))
53
  return false;
54
-
 
55
  // Compute allowed post types
56
  $post_types = get_post_types(array(), 'objects');
57
  $allowed_post_types = array_diff_key($post_types, array_fill_keys($avoid_post_types, true));
58
-
59
  // Return key-name values
60
  if ('keys-names' == $output) {
61
  $keys_names = array();
62
- foreach ($allowed_post_types as $key => $post_type)
63
  $keys_names[$key] = $post_type->labels->name;
 
64
  return $keys_names;
65
-
66
  // Return keys
67
  } elseif ('keys' == $output) {
68
  return array_keys($allowed_post_types);
69
-
70
  // Return names
71
  } elseif ('names' == $output) {
72
  $names = array();
73
- foreach ($allowed_post_types as $key => $post_type)
74
  $names[] = $post_type->labels->name;
 
75
  return $names;
76
  }
77
-
78
  // Default
79
  return $allowed_post_types;
80
  }
@@ -207,8 +210,9 @@ class WPLNST_Core_Types {
207
  $comment_types_values = array();
208
  $eq = array('approved' => '1', 'pending' => '0');
209
  foreach ($comment_types as $comment_type) {
210
- if (isset($eq[$comment_type]))
211
  $comment_types_values[] = $eq[$comment_type];
 
212
  }
213
  return $comment_types_values;
214
  }
@@ -380,8 +384,9 @@ class WPLNST_Core_Types {
380
  $raw = array();
381
  $codes = self::get_status_codes();
382
  foreach ($codes as $level => $status) {
383
- foreach ($status as $code => $description)
384
  $raw[$code] = $description;
 
385
  }
386
  return $raw;
387
  }
@@ -559,24 +564,26 @@ class WPLNST_Core_Types {
559
  * Resolve names, combined with levels and codes
560
  */
561
  public static function get_links_status_names_combined($status_levels_values, $status_codes_values) {
562
-
563
  // Initialize
564
  $names = array();
565
-
566
  // Resolve levels
567
  $status_codes = self::get_status_codes();
568
  $status_levels = self::get_status_levels();
569
  foreach ($status_levels as $key => $level_name) {
570
- if (in_array($key, $status_levels_values))
571
  $names[] = $key.'00s '.$level_name;
 
572
  if (isset($status_codes[$key])) {
573
  foreach ($status_codes[$key] as $code => $code_name) {
574
- if (in_array($code, $status_codes_values))
575
  $names[] = $code.' '.$code_name;
 
576
  }
577
  }
578
  }
579
-
580
  // Donde
581
  return $names;
582
  }
@@ -587,15 +594,17 @@ class WPLNST_Core_Types {
587
  * Resolve a name from key value
588
  */
589
  public static function get_field_value_name($array, $value, $default = false) {
590
-
591
  // Check name value
592
- if (isset($array[$value]))
593
  return $array[$value];
594
-
 
595
  // Check default value
596
- if (false !== $default && isset($array[$default]))
597
  return $array[$default];
598
-
 
599
  // Nothing
600
  return '';
601
  }
@@ -606,29 +615,32 @@ class WPLNST_Core_Types {
606
  * Resolve an array of names from an array of key values
607
  */
608
  public static function get_field_values_names($array, $values, $default = false) {
609
-
610
  // Initialize
611
  $names = array();
612
-
613
  // Enum values
614
  foreach ($values as $key) {
615
- if (isset($array[$key]))
616
  $names[] = $array[$key];
 
617
  }
618
-
619
  // Check default for empty names
620
  if (empty($names) && false !== $default) {
621
  if (!is_array($default)) {
622
- if (isset($array[$default]))
623
  $names[] = $array[$default];
 
624
  } else {
625
  foreach ($default as $key) {
626
- if (isset($array[$key]))
627
  $names[] = $array[$key];
 
628
  }
629
  }
630
  }
631
-
632
  // Done
633
  return $names;
634
  }
@@ -653,21 +665,23 @@ class WPLNST_Core_Types {
653
  * Check submitted elist and rearrange indexes
654
  */
655
  public static function check_post_elist($param, $default = array()) {
656
-
657
  // Decode value
658
  $elist = isset($_POST[$param])? @json_decode(stripslashes($_POST[$param]), true) : false;
659
-
660
  // Check decoding
661
- if (empty($elist) || !is_array($elist))
662
  return $default;
663
-
 
664
  // Arrange index
665
  $index = -1;
666
  foreach ($elist as &$value) {
667
- if (is_array($value))
668
  $value['index'] = ++$index;
 
669
  }
670
-
671
  // Done
672
  return @json_encode($elist);
673
  }
@@ -715,34 +729,35 @@ class WPLNST_Core_Types {
715
  * Check a value in array
716
  */
717
  public static function check_allowed_value($test, $allowed, $default = null) {
718
-
719
  // Is an array
720
  if (is_array($allowed)) {
721
-
722
  // Initialize
723
  $value = $default;
724
-
725
  // Source value as an array
726
  if (is_array($test)) {
727
  $value = array();
728
  foreach ($test as $key => $name) {
729
  $sel = ('on' == $name)? $key : $name;
730
- if (in_array($sel, $allowed))
731
  $value[] = $sel;
 
732
  }
733
-
734
  // Single value in allowed array
735
  } elseif (in_array($test, $allowed)) {
736
  $value = $test;
737
  }
738
-
739
  // Result value
740
  } else {
741
-
742
  // Comparison value
743
  $value = ($test === $allowed);
744
  }
745
-
746
  // Done
747
  return $value;
748
  }
1
  <?php
2
 
3
  /**
4
+ * Types class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_Types {
10
 
46
  * Post types allowed
47
  */
48
  public static function get_post_types($output = 'keys-names') {
49
+
50
  // Current avoid post types
51
  $avoid_post_types = apply_filters('wplnst_avoid_post_types', array_map('trim', explode(',', self::post_types_avoid)));
52
+ if (empty($avoid_post_types) || !is_array($avoid_post_types)) {
53
  return false;
54
+ }
55
+
56
  // Compute allowed post types
57
  $post_types = get_post_types(array(), 'objects');
58
  $allowed_post_types = array_diff_key($post_types, array_fill_keys($avoid_post_types, true));
59
+
60
  // Return key-name values
61
  if ('keys-names' == $output) {
62
  $keys_names = array();
63
+ foreach ($allowed_post_types as $key => $post_type) {
64
  $keys_names[$key] = $post_type->labels->name;
65
+ }
66
  return $keys_names;
67
+
68
  // Return keys
69
  } elseif ('keys' == $output) {
70
  return array_keys($allowed_post_types);
71
+
72
  // Return names
73
  } elseif ('names' == $output) {
74
  $names = array();
75
+ foreach ($allowed_post_types as $key => $post_type) {
76
  $names[] = $post_type->labels->name;
77
+ }
78
  return $names;
79
  }
80
+
81
  // Default
82
  return $allowed_post_types;
83
  }
210
  $comment_types_values = array();
211
  $eq = array('approved' => '1', 'pending' => '0');
212
  foreach ($comment_types as $comment_type) {
213
+ if (isset($eq[$comment_type])) {
214
  $comment_types_values[] = $eq[$comment_type];
215
+ }
216
  }
217
  return $comment_types_values;
218
  }
384
  $raw = array();
385
  $codes = self::get_status_codes();
386
  foreach ($codes as $level => $status) {
387
+ foreach ($status as $code => $description) {
388
  $raw[$code] = $description;
389
+ }
390
  }
391
  return $raw;
392
  }
564
  * Resolve names, combined with levels and codes
565
  */
566
  public static function get_links_status_names_combined($status_levels_values, $status_codes_values) {
567
+
568
  // Initialize
569
  $names = array();
570
+
571
  // Resolve levels
572
  $status_codes = self::get_status_codes();
573
  $status_levels = self::get_status_levels();
574
  foreach ($status_levels as $key => $level_name) {
575
+ if (in_array($key, $status_levels_values)) {
576
  $names[] = $key.'00s '.$level_name;
577
+ }
578
  if (isset($status_codes[$key])) {
579
  foreach ($status_codes[$key] as $code => $code_name) {
580
+ if (in_array($code, $status_codes_values)) {
581
  $names[] = $code.' '.$code_name;
582
+ }
583
  }
584
  }
585
  }
586
+
587
  // Donde
588
  return $names;
589
  }
594
  * Resolve a name from key value
595
  */
596
  public static function get_field_value_name($array, $value, $default = false) {
597
+
598
  // Check name value
599
+ if (isset($array[$value])) {
600
  return $array[$value];
601
+ }
602
+
603
  // Check default value
604
+ if (false !== $default && isset($array[$default])) {
605
  return $array[$default];
606
+ }
607
+
608
  // Nothing
609
  return '';
610
  }
615
  * Resolve an array of names from an array of key values
616
  */
617
  public static function get_field_values_names($array, $values, $default = false) {
618
+
619
  // Initialize
620
  $names = array();
621
+
622
  // Enum values
623
  foreach ($values as $key) {
624
+ if (isset($array[$key])) {
625
  $names[] = $array[$key];
626
+ }
627
  }
628
+
629
  // Check default for empty names
630
  if (empty($names) && false !== $default) {
631
  if (!is_array($default)) {
632
+ if (isset($array[$default])) {
633
  $names[] = $array[$default];
634
+ }
635
  } else {
636
  foreach ($default as $key) {
637
+ if (isset($array[$key])) {
638
  $names[] = $array[$key];
639
+ }
640
  }
641
  }
642
  }
643
+
644
  // Done
645
  return $names;
646
  }
665
  * Check submitted elist and rearrange indexes
666
  */
667
  public static function check_post_elist($param, $default = array()) {
668
+
669
  // Decode value
670
  $elist = isset($_POST[$param])? @json_decode(stripslashes($_POST[$param]), true) : false;
671
+
672
  // Check decoding
673
+ if (empty($elist) || !is_array($elist)) {
674
  return $default;
675
+ }
676
+
677
  // Arrange index
678
  $index = -1;
679
  foreach ($elist as &$value) {
680
+ if (is_array($value)) {
681
  $value['index'] = ++$index;
682
+ }
683
  }
684
+
685
  // Done
686
  return @json_encode($elist);
687
  }
729
  * Check a value in array
730
  */
731
  public static function check_allowed_value($test, $allowed, $default = null) {
732
+
733
  // Is an array
734
  if (is_array($allowed)) {
735
+
736
  // Initialize
737
  $value = $default;
738
+
739
  // Source value as an array
740
  if (is_array($test)) {
741
  $value = array();
742
  foreach ($test as $key => $name) {
743
  $sel = ('on' == $name)? $key : $name;
744
+ if (in_array($sel, $allowed)) {
745
  $value[] = $sel;
746
+ }
747
  }
748
+
749
  // Single value in allowed array
750
  } elseif (in_array($test, $allowed)) {
751
  $value = $test;
752
  }
753
+
754
  // Result value
755
  } else {
756
+
757
  // Comparison value
758
  $value = ($test === $allowed);
759
  }
760
+
761
  // Done
762
  return $value;
763
  }
core/url.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core URL class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
  class WPLNST_Core_URL {
10
 
@@ -39,25 +39,27 @@ class WPLNST_Core_URL {
39
  * Constructor
40
  */
41
  public function __construct() {
42
-
43
  // Blog home URL
44
  $this->home_url = rtrim(home_url(), '/');
45
-
46
  // Paranoid mode
47
- if (false !== ($pos = strpos($this->home_url, '#')))
48
  $this->home_url = mb_substr($this->home_url, 0, $pos);
49
-
 
50
  // Obtains host URL
51
  $home_parts = @parse_url($this->home_url);
52
  if (false !== $home_parts && isset($home_parts['host']) && '' !== $home_parts['host']) {
53
-
54
  // Site host
55
  $this->host = $home_parts['host'];
56
-
57
  // Check scheme
58
  $scheme = 'http';
59
- if (!empty($home_parts['scheme']) && in_array(strtolower($home_parts['scheme']), array('http', 'https')))
60
  $scheme = $home_parts['scheme'];
 
61
 
62
  // Define host URL
63
  $this->host_url = $scheme.'://'.$this->host;
@@ -75,7 +77,7 @@ class WPLNST_Core_URL {
75
  * URL analysis and fragmentation
76
  */
77
  public function parse($value, $parent_url = false) {
78
-
79
  // Initialize
80
  $raw = $value;
81
  $url = trim($raw);
@@ -84,147 +86,148 @@ class WPLNST_Core_URL {
84
  $relative = false;
85
  $protorel = false;
86
  $malformed = false;
87
-
88
  // Extract fragment
89
  $test_url = $url;
90
  if (false !== ($pos = strpos($test_url, '#'))) {
91
  $url = mb_substr($test_url, 0, $pos);
92
  $fragment = mb_substr($test_url, $pos);
93
  }
94
-
95
  // Check if begins with double slash
96
  if ('//' == mb_substr($url, 0, 2)) {
97
-
98
  // Initialize
99
  $protorel = true;
100
  $malformed = true;
101
-
102
  // Set full URL
103
  $full_url = ((0 === stripos($this->home_url, 'https'))? 'https' : 'http').':'.$url;
104
-
105
  // Check scheme and host
106
  if (false !== ($parts = @parse_url($full_url)) && !empty($parts['scheme']) && !empty($parts['host'])) {
107
-
108
  // No malformed
109
  $malformed = false;
110
-
111
  // Remove possible fragment
112
  $parts['fragment'] = null;
113
-
114
  // Final URL
115
  $url = $this->unparse_url($parts);
116
  }
117
-
118
  // Check if begins with a single slash (absolute relative)
119
  } elseif ('/' == mb_substr($url, 0, 1)) {
120
-
121
  // By default
122
  $malformed = true;
123
-
124
  // Execute parent URL filter
125
  $parent_url = apply_filters('wplnst_relative_parent_url', $parent_url);
126
-
127
  // Check parent
128
  if (false !== $parent_url && !is_array($parent_url)) {
129
-
130
  // Check parent URL
131
  $parent_parts = @parse_url($parent_url);
132
  if (false !== $parent_parts && isset($parent_parts['host']) && '' !== $parent_parts['host']) {
133
-
134
  // Check scheme
135
  $scheme = 'http';
136
- if (!empty($parent_parts['scheme']) && in_array(strtolower($parent_parts['scheme']), array('http', 'https')))
137
  $scheme = $parent_parts['scheme'];
138
-
 
139
  // Compose full URL
140
  $url = $scheme.'://'.trim($parent_parts['host'], '/').'/'.ltrim($url, '/');
141
-
142
  // No malfomed
143
  $malformed = false;
144
-
145
  // Is absolute
146
  $absolute = true;
147
-
148
  // Extract parts again
149
  $parts = @parse_url($url);
150
  }
151
-
152
  // This site
153
  } else {
154
-
155
  // Set full URL
156
  $home_url = isset($this->host_url)? $this->host_url : $this->home_url;
157
  $full_url = rtrim($home_url, '/').$url;
158
-
159
  // Check scheme and host
160
  if (false !== ($parts = @parse_url($full_url)) && !empty($parts['scheme']) && !empty($parts['host'])) {
161
-
162
  // No malfomed
163
  $malformed = false;
164
-
165
  // Is absolute
166
  $absolute = true;
167
-
168
  // Remove possible fragment
169
  $parts['fragment'] = null;
170
-
171
  // Final URL
172
  $url = $this->unparse_url($parts);
173
  }
174
  }
175
-
176
  // Other
177
  } else {
178
-
179
  // Split parts
180
  $parts = @parse_url($url);
181
  if (false === $parts) {
182
-
183
  // Malformed URL
184
  $malformed = true;
185
-
186
  // First relative check
187
  } elseif (empty($parts['scheme'])) {
188
-
189
  // Relative URL
190
  $relative = true;
191
-
192
  // Execute parent URL filter
193
  $parent_url = apply_filters('wplnst_relative_parent_url', $parent_url);
194
-
195
  // Try to compose
196
  if (false !== $parent_url && !is_array($parent_url)) {
197
-
198
  // Absolutize
199
  $url = $this->absolutize($url, $parent_url);
200
-
201
  // Extract parts again
202
  $parts = @parse_url($url);
203
-
204
  // This host
205
  } else {
206
-
207
  // Absolutize
208
  $url = $this->absolutize($url, $this->home_url);
209
-
210
  // Extract parts again
211
  $parts = @parse_url($url);
212
  }
213
  }
214
  }
215
-
216
  // Check scheme, host, path and query
217
  $scheme = isset($parts['scheme'])? $parts['scheme'] : null;
218
  $host = isset($parts['host'])? $parts['host'] : null;
219
  $path = isset($parts['path'])? $parts['path'] : null;
220
  $query = isset($parts['query'])? $parts['query'] : null;
221
-
222
  // Check link scope
223
  $scope = (isset($host) && isset($scheme))? $this->get_scope($host, $scheme) : null;
224
-
225
  // Check link fragment
226
  $fragment = isset($fragment)? $fragment : (isset($parts['fragment'])? $parts['fragment'] : null);
227
-
228
  // Done
229
  return array(
230
  'url' => $url,
@@ -269,33 +272,36 @@ class WPLNST_Core_URL {
269
  * Absolutize relative URL from a given permalink
270
  */
271
  public function absolutize($relative_url, $permalink) {
272
-
273
  // Parse permalink
274
  $permalink_parts = @parse_url($permalink);
275
- if (false === $permalink_parts)
276
  return false;
277
-
 
278
  // Relative with arguments
279
  if ('?' == mb_substr($relative_url, 0, 1)) {
280
-
281
  // Remove permalink fragment
282
- if (($pos = strpos($permalink, '#')) > 0)
283
  $permalink = mb_substr($permalink, 0, $pos);
284
-
 
285
  // Concatenation
286
  return $permalink.$relative_url;
287
-
288
  // Explode
289
  } else {
290
-
291
  // Initialize
292
  $path = array();
293
  $base = empty($permalink_parts['path'])? '/' : $permalink_parts['path'];
294
-
295
  // Check last file
296
- if ('/' != mb_substr($base, -1))
297
  $base = dirname($base);
298
-
 
299
  // URL parts
300
  $parts = explode('/', $relative_url);
301
  foreach ($parts as $part) {
@@ -305,13 +311,13 @@ class WPLNST_Core_URL {
305
  $path[] = $part;
306
  }
307
  }
308
-
309
  // Compose new path
310
  $permalink_parts['path'] = rtrim($base, '/').'/'.implode('/', $path).(('/' == mb_substr($relative_url, -1))? '/' : '');
311
 
312
  // Remove permalink parts fragment
313
  $permalink_parts['fragment'] = null;
314
-
315
  // Done
316
  return $this->unparse_url($permalink_parts);
317
  }
@@ -326,8 +332,9 @@ class WPLNST_Core_URL {
326
  public function extract_attributes($tag) {
327
  $attr = array();
328
  if (preg_match_all('/(\S+)=["'."'".']?((?:.(?!["'."'".']?\s+(?:\S+)=|[>"'."'".']))+.)["'."'".']?/', $tag, $matches, PREG_SET_ORDER) > 0) {
329
- foreach ($matches as $match)
330
  $attr[strtolower($match[1])] = $match[2];
 
331
  }
332
  return $attr;
333
  }
@@ -347,14 +354,14 @@ class WPLNST_Core_URL {
347
  * Check host and scheme and compare from blog host
348
  */
349
  public function get_scope($host, $scheme) {
350
-
351
  // Check scheme
352
  if (isset($this->host) && in_array(strtolower($scheme), array('http', 'https', 'ftp'))) {
353
  $test_host = (0 === stripos($host, 'www.'))? mb_substr($host, 4) : $host;
354
  $test_this_host = (0 === stripos($this->host, 'www.'))? mb_substr($this->host, 4) : $this->host;
355
  return (strtolower($test_host) == strtolower($test_this_host))? 'internal' : 'external';
356
  }
357
-
358
  // No valid
359
  return null;
360
  }
1
  <?php
2
 
3
  /**
4
+ * URL class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
  class WPLNST_Core_URL {
10
 
39
  * Constructor
40
  */
41
  public function __construct() {
42
+
43
  // Blog home URL
44
  $this->home_url = rtrim(home_url(), '/');
45
+
46
  // Paranoid mode
47
+ if (false !== ($pos = strpos($this->home_url, '#'))) {
48
  $this->home_url = mb_substr($this->home_url, 0, $pos);
49
+ }
50
+
51
  // Obtains host URL
52
  $home_parts = @parse_url($this->home_url);
53
  if (false !== $home_parts && isset($home_parts['host']) && '' !== $home_parts['host']) {
54
+
55
  // Site host
56
  $this->host = $home_parts['host'];
57
+
58
  // Check scheme
59
  $scheme = 'http';
60
+ if (!empty($home_parts['scheme']) && in_array(strtolower($home_parts['scheme']), array('http', 'https'))) {
61
  $scheme = $home_parts['scheme'];
62
+ }
63
 
64
  // Define host URL
65
  $this->host_url = $scheme.'://'.$this->host;
77
  * URL analysis and fragmentation
78
  */
79
  public function parse($value, $parent_url = false) {
80
+
81
  // Initialize
82
  $raw = $value;
83
  $url = trim($raw);
86
  $relative = false;
87
  $protorel = false;
88
  $malformed = false;
89
+
90
  // Extract fragment
91
  $test_url = $url;
92
  if (false !== ($pos = strpos($test_url, '#'))) {
93
  $url = mb_substr($test_url, 0, $pos);
94
  $fragment = mb_substr($test_url, $pos);
95
  }
96
+
97
  // Check if begins with double slash
98
  if ('//' == mb_substr($url, 0, 2)) {
99
+
100
  // Initialize
101
  $protorel = true;
102
  $malformed = true;
103
+
104
  // Set full URL
105
  $full_url = ((0 === stripos($this->home_url, 'https'))? 'https' : 'http').':'.$url;
106
+
107
  // Check scheme and host
108
  if (false !== ($parts = @parse_url($full_url)) && !empty($parts['scheme']) && !empty($parts['host'])) {
109
+
110
  // No malformed
111
  $malformed = false;
112
+
113
  // Remove possible fragment
114
  $parts['fragment'] = null;
115
+
116
  // Final URL
117
  $url = $this->unparse_url($parts);
118
  }
119
+
120
  // Check if begins with a single slash (absolute relative)
121
  } elseif ('/' == mb_substr($url, 0, 1)) {
122
+
123
  // By default
124
  $malformed = true;
125
+
126
  // Execute parent URL filter
127
  $parent_url = apply_filters('wplnst_relative_parent_url', $parent_url);
128
+
129
  // Check parent
130
  if (false !== $parent_url && !is_array($parent_url)) {
131
+
132
  // Check parent URL
133
  $parent_parts = @parse_url($parent_url);
134
  if (false !== $parent_parts && isset($parent_parts['host']) && '' !== $parent_parts['host']) {
135
+
136
  // Check scheme
137
  $scheme = 'http';
138
+ if (!empty($parent_parts['scheme']) && in_array(strtolower($parent_parts['scheme']), array('http', 'https'))) {
139
  $scheme = $parent_parts['scheme'];
140
+ }
141
+
142
  // Compose full URL
143
  $url = $scheme.'://'.trim($parent_parts['host'], '/').'/'.ltrim($url, '/');
144
+
145
  // No malfomed
146
  $malformed = false;
147
+
148
  // Is absolute
149
  $absolute = true;
150
+
151
  // Extract parts again
152
  $parts = @parse_url($url);
153
  }
154
+
155
  // This site
156
  } else {
157
+
158
  // Set full URL
159
  $home_url = isset($this->host_url)? $this->host_url : $this->home_url;
160
  $full_url = rtrim($home_url, '/').$url;
161
+
162
  // Check scheme and host
163
  if (false !== ($parts = @parse_url($full_url)) && !empty($parts['scheme']) && !empty($parts['host'])) {
164
+
165
  // No malfomed
166
  $malformed = false;
167
+
168
  // Is absolute
169
  $absolute = true;
170
+
171
  // Remove possible fragment
172
  $parts['fragment'] = null;
173
+
174
  // Final URL
175
  $url = $this->unparse_url($parts);
176
  }
177
  }
178
+
179
  // Other
180
  } else {
181
+
182
  // Split parts
183
  $parts = @parse_url($url);
184
  if (false === $parts) {
185
+
186
  // Malformed URL
187
  $malformed = true;
188
+
189
  // First relative check
190
  } elseif (empty($parts['scheme'])) {
191
+
192
  // Relative URL
193
  $relative = true;
194
+
195
  // Execute parent URL filter
196
  $parent_url = apply_filters('wplnst_relative_parent_url', $parent_url);
197
+
198
  // Try to compose
199
  if (false !== $parent_url && !is_array($parent_url)) {
200
+
201
  // Absolutize
202
  $url = $this->absolutize($url, $parent_url);
203
+
204
  // Extract parts again
205
  $parts = @parse_url($url);
206
+
207
  // This host
208
  } else {
209
+
210
  // Absolutize
211
  $url = $this->absolutize($url, $this->home_url);
212
+
213
  // Extract parts again
214
  $parts = @parse_url($url);
215
  }
216
  }
217
  }
218
+
219
  // Check scheme, host, path and query
220
  $scheme = isset($parts['scheme'])? $parts['scheme'] : null;
221
  $host = isset($parts['host'])? $parts['host'] : null;
222
  $path = isset($parts['path'])? $parts['path'] : null;
223
  $query = isset($parts['query'])? $parts['query'] : null;
224
+
225
  // Check link scope
226
  $scope = (isset($host) && isset($scheme))? $this->get_scope($host, $scheme) : null;
227
+
228
  // Check link fragment
229
  $fragment = isset($fragment)? $fragment : (isset($parts['fragment'])? $parts['fragment'] : null);
230
+
231
  // Done
232
  return array(
233
  'url' => $url,
272
  * Absolutize relative URL from a given permalink
273
  */
274
  public function absolutize($relative_url, $permalink) {
275
+
276
  // Parse permalink
277
  $permalink_parts = @parse_url($permalink);
278
+ if (false === $permalink_parts) {
279
  return false;
280
+ }
281
+
282
  // Relative with arguments
283
  if ('?' == mb_substr($relative_url, 0, 1)) {
284
+
285
  // Remove permalink fragment
286
+ if (($pos = strpos($permalink, '#')) > 0) {
287
  $permalink = mb_substr($permalink, 0, $pos);
288
+ }
289
+
290
  // Concatenation
291
  return $permalink.$relative_url;
292
+
293
  // Explode
294
  } else {
295
+
296
  // Initialize
297
  $path = array();
298
  $base = empty($permalink_parts['path'])? '/' : $permalink_parts['path'];
299
+
300
  // Check last file
301
+ if ('/' != mb_substr($base, -1)) {
302
  $base = dirname($base);
303
+ }
304
+
305
  // URL parts
306
  $parts = explode('/', $relative_url);
307
  foreach ($parts as $part) {
311
  $path[] = $part;
312
  }
313
  }
314
+
315
  // Compose new path
316
  $permalink_parts['path'] = rtrim($base, '/').'/'.implode('/', $path).(('/' == mb_substr($relative_url, -1))? '/' : '');
317
 
318
  // Remove permalink parts fragment
319
  $permalink_parts['fragment'] = null;
320
+
321
  // Done
322
  return $this->unparse_url($permalink_parts);
323
  }
332
  public function extract_attributes($tag) {
333
  $attr = array();
334
  if (preg_match_all('/(\S+)=["'."'".']?((?:.(?!["'."'".']?\s+(?:\S+)=|[>"'."'".']))+.)["'."'".']?/', $tag, $matches, PREG_SET_ORDER) > 0) {
335
+ foreach ($matches as $match) {
336
  $attr[strtolower($match[1])] = $match[2];
337
+ }
338
  }
339
  return $attr;
340
  }
354
  * Check host and scheme and compare from blog host
355
  */
356
  public function get_scope($host, $scheme) {
357
+
358
  // Check scheme
359
  if (isset($this->host) && in_array(strtolower($scheme), array('http', 'https', 'ftp'))) {
360
  $test_host = (0 === stripos($host, 'www.'))? mb_substr($host, 4) : $host;
361
  $test_this_host = (0 === stripos($this->host, 'www.'))? mb_substr($this->host, 4) : $this->host;
362
  return (strtolower($test_host) == strtolower($test_this_host))? 'internal' : 'external';
363
  }
364
+
365
  // No valid
366
  return null;
367
  }
core/util-math.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Util Math functions
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
 
10
 
@@ -13,24 +13,26 @@
13
  * Format size from bytes to KB, MB, GB or TB
14
  */
15
  function wplnst_format_bytes($bytes, $precision = 3, $number_format = true) {
16
-
17
  $units = array('B', 'KB', 'MB', 'GB', 'TB');
18
-
19
- $bytes = max($bytes, 0);
20
- $pow = floor(($bytes? log($bytes) : 0) / log(1024));
21
  $pow = min($pow, count($units) - 1);
22
-
23
  // Uncomment one of the following alternatives
24
  $bytes /= pow(1024, $pow);
25
  if (0 == $pow) {
26
  $pow = 1;
27
- if ($bytes > 0)
28
  $bytes /= 1024;
 
29
  }
30
-
31
  $value = round($bytes, $precision);
32
- if ($number_format && function_exists('number_format_i18n'))
33
  $value = number_format_i18n($value, $precision);
34
-
 
35
  return $value . ' ' . $units[$pow];
36
  }
1
  <?php
2
 
3
  /**
4
+ * Util Math functions
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
 
10
 
13
  * Format size from bytes to KB, MB, GB or TB
14
  */
15
  function wplnst_format_bytes($bytes, $precision = 3, $number_format = true) {
16
+
17
  $units = array('B', 'KB', 'MB', 'GB', 'TB');
18
+
19
+ $bytes = max($bytes, 0);
20
+ $pow = floor(($bytes? log($bytes) : 0) / log(1024));
21
  $pow = min($pow, count($units) - 1);
22
+
23
  // Uncomment one of the following alternatives
24
  $bytes /= pow(1024, $pow);
25
  if (0 == $pow) {
26
  $pow = 1;
27
+ if ($bytes > 0) {
28
  $bytes /= 1024;
29
+ }
30
  }
31
+
32
  $value = round($bytes, $precision);
33
+ if ($number_format && function_exists('number_format_i18n')) {
34
  $value = number_format_i18n($value, $precision);
35
+ }
36
+
37
  return $value . ' ' . $units[$pow];
38
  }
core/util-string.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Util String functions
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
 
10
 
@@ -16,34 +16,36 @@ function wplnst_crop_text($text, $chars, $dots = '...') {
16
 
17
  // Remove HTML tags
18
  $text = strip_tags(preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $text));
19
-
20
  // All text
21
  $text = trim($text);
22
- if (strlen($text) <= $chars)
23
  return $text;
24
-
 
25
  // Crop text
26
  $text = substr($text, 0, $chars);
27
-
28
  // Remove punctuation
29
  $text = rtrim($text, '.');
30
  $text = rtrim($text, ',');
31
  $text = rtrim($text, ';');
32
  $text = rtrim($text, ':');
33
-
34
  // Check last char
35
  if (mb_substr($text, -1) != ' ') {
36
  $pos = strrpos($text, ' ');
37
- if ($pos > 0)
38
  $text = substr($text, 0, $pos);
 
39
  }
40
-
41
  // Last chars
42
  $text = rtrim($text, '.');
43
  $text = rtrim($text, ',');
44
  $text = rtrim($text, ';');
45
  $text = rtrim($text, ':');
46
-
47
  // Done
48
  return $text.$dots;
49
  }
1
  <?php
2
 
3
  /**
4
+ * Util String functions
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
 
10
 
16
 
17
  // Remove HTML tags
18
  $text = strip_tags(preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $text));
19
+
20
  // All text
21
  $text = trim($text);
22
+ if (strlen($text) <= $chars) {
23
  return $text;
24
+ }
25
+
26
  // Crop text
27
  $text = substr($text, 0, $chars);
28
+
29
  // Remove punctuation
30
  $text = rtrim($text, '.');
31
  $text = rtrim($text, ',');
32
  $text = rtrim($text, ';');
33
  $text = rtrim($text, ':');
34
+
35
  // Check last char
36
  if (mb_substr($text, -1) != ' ') {
37
  $pos = strrpos($text, ' ');
38
+ if ($pos > 0) {
39
  $text = substr($text, 0, $pos);
40
+ }
41
  }
42
+
43
  // Last chars
44
  $text = rtrim($text, '.');
45
  $text = rtrim($text, ',');
46
  $text = rtrim($text, ';');
47
  $text = rtrim($text, ':');
48
+
49
  // Done
50
  return $text.$dots;
51
  }
core/util.php CHANGED
@@ -1,16 +1,17 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Core Util functions
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Core
8
  */
9
 
10
 
11
 
12
  // Load dependencies
13
- require_once(dirname(__FILE__).'/settings.php');
 
14
 
15
 
16
 
@@ -27,8 +28,9 @@ function wplnst_require($section, $filename) {
27
  * Requires multiple files for the same section
28
  */
29
  function wplnst_require_section($section, $filenames) {
30
- foreach ($filenames as $filename)
31
  wplnst_require($section, $filename);
 
32
  }
33
 
34
 
@@ -64,51 +66,27 @@ function wplnst_get_tsetting($name, $default = true) {
64
  * Check if cURL is enabled in this system
65
  */
66
  function wplnst_is_curl_enabled() {
67
-
68
  // Last status
69
  static $is_enabled;
70
- if (isset($is_enabled))
71
  return $is_enabled;
72
-
 
73
  // Simple check, but it may have been overwritten
74
  if (!function_exists('curl_version')) {
75
  $is_enabled = false;
76
  return false;
77
  }
78
-
79
  // Check extension
80
  $extensions = @get_loaded_extensions();
81
  if (!empty($extensions) && is_array($extensions) && in_array('curl', $extensions)) {
82
  $is_enabled = true;
83
  return true;
84
  }
85
-
86
  // Not found
87
  $is_enabled = false;
88
  return false;
89
- }
90
-
91
-
92
-
93
- /**
94
- * Check debug flag
95
- */
96
- function wplnst_is_debug() {
97
- return (defined('WPLNST_DEBUG') && WPLNST_DEBUG);
98
- }
99
-
100
-
101
-
102
- /**
103
- * Output plugin debug
104
- */
105
- function wplnst_debug($message, $tag = '') {
106
-
107
- // Check debug
108
- if (!wplnst_is_debug())
109
- return;
110
-
111
- // Default output
112
- if (!defined('WPLNST_DEBUG_OUTPUT') || 'error_log' == WPLNST_DEBUG_OUTPUT)
113
- error_log('WPLNST'.(empty($tag)? '' : ' ['.$tag.']').' - '.$message);
114
  }
1
  <?php
2
 
3
  /**
4
+ * Util functions
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Core
8
  */
9
 
10
 
11
 
12
  // Load dependencies
13
+ require_once dirname(__FILE__).'/debug.php';
14
+ require_once dirname(__FILE__).'/settings.php';
15
 
16
 
17
 
28
  * Requires multiple files for the same section
29
  */
30
  function wplnst_require_section($section, $filenames) {
31
+ foreach ($filenames as $filename) {
32
  wplnst_require($section, $filename);
33
+ }
34
  }
35
 
36
 
66
  * Check if cURL is enabled in this system
67
  */
68
  function wplnst_is_curl_enabled() {
69
+
70
  // Last status
71
  static $is_enabled;
72
+ if (isset($is_enabled)) {
73
  return $is_enabled;
74
+ }
75
+
76
  // Simple check, but it may have been overwritten
77
  if (!function_exists('curl_version')) {
78
  $is_enabled = false;
79
  return false;
80
  }
81
+
82
  // Check extension
83
  $extensions = @get_loaded_extensions();
84
  if (!empty($extensions) && is_array($extensions) && in_array('curl', $extensions)) {
85
  $is_enabled = true;
86
  return true;
87
  }
88
+
89
  // Not found
90
  $is_enabled = false;
91
  return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  }
languages/wp-link-status.pot CHANGED
File without changes
readme.txt CHANGED
@@ -1,10 +1,11 @@
1
  === WP Broken Link Status Checker ===
2
  Contributors: seedplugins, pauiglesias
3
- Tags: broken links, broken, links, crawler, headers, http, nofollow, redirections, scan, status, checker, url
 
4
  Requires at least: 3.4
5
- Tested up to: 4.7.1
6
- Stable tag: 1.0.4
7
  License: GPLv2 or later
 
8
 
9
  Link checker of all your content links and images, looking for broken links, check link redirections, warn of nofollow links, etc.
10
 
@@ -113,6 +114,19 @@ You can add the custom field name in the "Content options" tab of the scan, sele
113
 
114
  == Changelog ==
115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  = 1.0.4 =
117
  September 11th, 2016
118
 
1
  === WP Broken Link Status Checker ===
2
  Contributors: seedplugins, pauiglesias
3
+ Tested up to: 5.1
4
+ Requires PHP: 5.6
5
  Requires at least: 3.4
6
+ Stable tag: 1.0.5
 
7
  License: GPLv2 or later
8
+ Tags: broken links, broken, links, crawler, headers, http, nofollow, redirections, scan, status, checker, url
9
 
10
  Link checker of all your content links and images, looking for broken links, check link redirections, warn of nofollow links, etc.
11
 
114
 
115
  == Changelog ==
116
 
117
+ = 1.0.5 =
118
+ March 7th, 2019
119
+
120
+ * Tested with PHP 7.0 and PHP 7.2
121
+ * Tested with WP 5.x and Gutenberg
122
+ * Coding style corrections
123
+ * Fixed several soft bugs
124
+ * Allow activation/deactivation/uninstall without admin area restriction
125
+ * Prevent network-wide plugin activation for multisite installs
126
+ * Remove threads with off status to avoid TEXT field overflow
127
+ * More time to HTTP CURL spawn method to run
128
+ * Improvements in debug and trace mode
129
+
130
  = 1.0.4 =
131
  September 11th, 2016
132
 
views/extensions.php CHANGED
@@ -1,13 +1,13 @@
1
  <?php
2
 
3
  // Load views class
4
- require_once(dirname(__FILE__).'/views.php');
5
 
6
  /**
7
- * WP Link Status Views Extensions class
8
  *
9
  * @package WP Link Status
10
- * @subpackage WP Link Status Views
11
  */
12
  class WPLNST_Views_Extensions extends WPLNST_Views {
13
 
@@ -17,58 +17,58 @@ class WPLNST_Views_Extensions extends WPLNST_Views {
17
  * Show scan edit form
18
  */
19
  public static function view($args) {
20
-
21
  // Vars
22
  extract($args);
23
-
24
  // Plugin images
25
  $base_url = plugins_url('assets/images/extensions/', WPLNST_FILE);
26
-
27
  ?><div id="wplnst-extensions">
28
-
29
-
30
  <div class="wplnst-extensions-section">
31
-
32
  <p><a href="http://seedplugins.com/wp-link-status/" target="_blank"><img src="<?php echo $base_url.'pro-banner.jpg'; ?>" width="590" height="300" border="0" /></a></p>
33
-
34
  <p style="width: 590px; text-align: center;"><a href="http://seedplugins.com/wp-link-status/" target="_blank" class="button-primary">Get WP Link Status Pro version</a></p>
35
-
36
  </div>
37
-
38
-
39
  <div class="wplnst-extensions-section">
40
-
41
  <h3>Advanced filters</h3>
42
-
43
  <p><img src="<?php echo $base_url.'wpls-web-crawler-results-advanced.png'; ?>" width="800" height="120" border="0" /></p>
44
-
45
  </div>
46
-
47
-
48
  <div class="wplnst-extensions-section">
49
-
50
  <h3>Inline result editing</h3>
51
-
52
  <p><img src="<?php echo $base_url.'wpls-web-crawler-results-actions.png'; ?>" width="800" height="100" border="0" /></p>
53
-
54
  <p><img src="<?php echo $base_url.'wpls-web-crawler-edit.png'; ?>" width="800" height="300" border="0" /></p>
55
-
56
  </div>
57
-
58
-
59
  <div class="wplnst-extensions-section">
60
-
61
  <h3>Extra URL Tools</h3>
62
-
63
  <p><img src="<?php echo $base_url.'wpls-web-crawler-url-tools.png'; ?>" width="800" height="363" border="0" /></p>
64
-
65
  <p><img src="<?php echo $base_url.'wpls-web-crawler-url-tools-results.png'; ?>" width="800" height="427" border="0" /></p>
66
-
67
  </div>
68
-
69
  <p style="width: 800px; text-align: center;"><a href="http://seedplugins.com/wp-link-status/" target="_blank" class="button-primary">Get WP Link Status Pro version</a></p>
70
-
71
-
72
  </div><?php
73
  }
74
 
1
  <?php
2
 
3
  // Load views class
4
+ require_once dirname(__FILE__).'/views.php';
5
 
6
  /**
7
+ * Extensions class
8
  *
9
  * @package WP Link Status
10
+ * @subpackage Views
11
  */
12
  class WPLNST_Views_Extensions extends WPLNST_Views {
13
 
17
  * Show scan edit form
18
  */
19
  public static function view($args) {
20
+
21
  // Vars
22
  extract($args);
23
+
24
  // Plugin images
25
  $base_url = plugins_url('assets/images/extensions/', WPLNST_FILE);
26
+
27
  ?><div id="wplnst-extensions">
28
+
29
+
30
  <div class="wplnst-extensions-section">
31
+
32
  <p><a href="http://seedplugins.com/wp-link-status/" target="_blank"><img src="<?php echo $base_url.'pro-banner.jpg'; ?>" width="590" height="300" border="0" /></a></p>
33
+
34
  <p style="width: 590px; text-align: center;"><a href="http://seedplugins.com/wp-link-status/" target="_blank" class="button-primary">Get WP Link Status Pro version</a></p>
35
+
36
  </div>
37
+
38
+
39
  <div class="wplnst-extensions-section">
40
+
41
  <h3>Advanced filters</h3>
42
+
43
  <p><img src="<?php echo $base_url.'wpls-web-crawler-results-advanced.png'; ?>" width="800" height="120" border="0" /></p>
44
+
45
  </div>
46
+
47
+
48
  <div class="wplnst-extensions-section">
49
+
50
  <h3>Inline result editing</h3>
51
+
52
  <p><img src="<?php echo $base_url.'wpls-web-crawler-results-actions.png'; ?>" width="800" height="100" border="0" /></p>
53
+
54
  <p><img src="<?php echo $base_url.'wpls-web-crawler-edit.png'; ?>" width="800" height="300" border="0" /></p>
55
+
56
  </div>
57
+
58
+
59
  <div class="wplnst-extensions-section">
60
+
61
  <h3>Extra URL Tools</h3>
62
+
63
  <p><img src="<?php echo $base_url.'wpls-web-crawler-url-tools.png'; ?>" width="800" height="363" border="0" /></p>
64
+
65
  <p><img src="<?php echo $base_url.'wpls-web-crawler-url-tools-results.png'; ?>" width="800" height="427" border="0" /></p>
66
+
67
  </div>
68
+
69
  <p style="width: 800px; text-align: center;"><a href="http://seedplugins.com/wp-link-status/" target="_blank" class="button-primary">Get WP Link Status Pro version</a></p>
70
+
71
+
72
  </div><?php
73
  }
74
 
views/scans-edit.php CHANGED
@@ -1,13 +1,13 @@
1
  <?php
2
 
3
  // Load views class
4
- require_once(dirname(__FILE__).'/views.php');
5
 
6
  /**
7
- * WP Link Status Views Scans Edit class
8
  *
9
  * @package WP Link Status
10
- * @subpackage WP Link Status Views
11
  */
12
  class WPLNST_Views_Scans_Edit extends WPLNST_Views {
13
 
@@ -17,73 +17,74 @@ class WPLNST_Views_Scans_Edit extends WPLNST_Views {
17
  * Show scan edit form
18
  */
19
  public static function view($args) {
20
-
21
  // Vars
22
  extract($args);
23
-
24
  // Initialize
25
  $is_ready = true;
26
  $editable = ('wait' == $scan->status);
27
-
28
  // Check errors
29
  $link_types_error = $post_types_error = $post_status_error = $link_status_error = false;
30
  if (!empty($notice_ready) && is_array($notice_ready)) {
31
-
32
  // Inside form errors
33
  $link_types_error = isset($notice_ready['link_types']);
34
  $post_types_error = isset($notice_ready['post_types']);
35
  $post_status_error = isset($notice_ready['post_status']);
36
  $link_status_error = isset($notice_ready['link_status']);
37
-
38
  // Determine if ready
39
  $is_ready = !($link_types_error || $post_types_error || $post_status_error || $link_status_error);
40
-
41
  // Show notice errors
42
  echo '<div class="error notice">';
43
- foreach ($notice_ready as $notice_key => $notice_title)
44
  echo '<p>'.$notice_title.'</p>';
 
45
  echo '</div>';
46
  } ?>
47
-
48
  <?php if ($is_ready && $scan->id > 0) :
49
-
50
  // Prepare URLs
51
  $results_url = esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan->id));
52
  $start_url = esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($scan->id, 'on', $scan->hash));
53
  $stop_url = esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($scan->id, 'off', $scan->hash)); ?>
54
-
55
  <?php if ('stop' == $scan->status) : ?>
56
-
57
  <div class="notice"><p><?php printf(__('The crawler for this scan is <strong>stopped</strong> but you can see the <a href="%s">crawling results</a> collected data.', 'wplnst'), $results_url); if ($more_scans) : echo ' '; printf(__('Or you can <a href="%s">start again the crawler</a>.', 'wplnst'), $start_url); endif; ?></p></div>
58
-
59
  <?php elseif ('play' == $scan->status) : ?>
60
-
61
  <?php if (empty($_POST['scan_run']) && empty($_GET['started'])) : ?>
62
-
63
  <div class="notice"><p><?php printf(__('The crawler for this scan is <strong>running</strong> and you can see its <a href="%s">crawling results data</a>.', 'wplnst'), $results_url); echo ' '; printf(__('If needed you can <a href="%s">stop the crawler</a>.', 'wplnst'), $stop_url); ?></p></div>
64
-
65
  <?php endif; ?>
66
-
67
  <?php elseif ('end' == $scan->status) : ?>
68
-
69
  <div class="notice"><p><?php printf(__('The crawler is completed and you can see all its <a href="%s">crawling results</a>.', 'wplnst'), $results_url); ?></p></div>
70
-
71
  <?php endif; ?>
72
-
73
  <?php endif; ?>
74
-
75
  <form method="post" id="wplnst-form" action="<?php echo esc_url($action); ?>">
76
-
77
  <input type="hidden" name="scan_id" id="wplnst-scan-id" value="<?php echo esc_attr($scan->id); ?>" />
78
  <input type="hidden" name="scan_run" id="wplnst-scan-run" value="" />
79
  <input type="hidden" name="scan_edit_nonce" value="<?php echo esc_attr($nonce); ?>" />
80
-
81
  <input type="hidden" name="scan_custom_fields" id="wplnst-scan-custom-fields" value='<?php echo self::esc_attr_elist($scan->custom_fields); ?>' />
82
  <input type="hidden" name="scan_anchor_filters" id="wplnst-scan-anchor-filters" value='<?php echo self::esc_attr_elist($scan->anchor_filters); ?>' />
83
  <input type="hidden" name="scan_include_urls" id="wplnst-scan-include-urls" value='<?php echo self::esc_attr_elist($scan->include_urls); ?>' />
84
  <input type="hidden" name="scan_exclude_urls" id="wplnst-scan-exclude-urls" value='<?php echo self::esc_attr_elist($scan->exclude_urls); ?>' />
85
  <input type="hidden" name="scan_html_attributes" id="wplnst-scan-html-attributes" value='<?php echo self::esc_attr_elist($scan->html_attributes); ?>' />
86
-
87
  <h2 id="wplnst-tabs-nav" class="nav-tab-wrapper">
88
  <a id="wplnst-general-tab" href="#top#wplnst-general" class="nav-tab"<?php if ($link_types_error) echo ' style="color: red;"'; ?>><?php _e('General', 'wplnst'); ?></a>
89
  <a id="wplnst-content-tab" href="#top#wplnst-content" class="nav-tab"<?php if ($post_types_error || $post_status_error) echo ' style="color: red;"'; ?>><?php _e('Content options', 'wplnst'); ?></a>
@@ -92,251 +93,251 @@ class WPLNST_Views_Scans_Edit extends WPLNST_Views {
92
  <?php if (false) : ?><a id="wplnst-scheduled-tab" href="#top#wplnst-scheduled" class="nav-tab"><?php _e('Schedule', 'wplnst'); ?></a><?php endif; ?>
93
  <a id="wplnst-advanced-tab" href="#top#wplnst-advanced" class="nav-tab"><?php _e('Advanced', 'wplnst'); ?></a>
94
  </h2>
95
-
96
  <div id="wplnst-tabs" class="wplnst-tabs-scan-edit">
97
-
98
  <div id="wplnst-general" class="wplnst-tab wplnst-tab-default">
99
-
100
  <table class="form-table">
101
-
102
  <tr>
103
  <th><label for="tx-name"><?php _e('Scan name', 'wplnst'); ?></label></th>
104
  <td><input type="text" name="tx-name" id="tx-name" value="<?php echo esc_attr($scan->name); ?>" class="regular-text" maxlength="255" /> (<?php _e('optional', 'wplnst'); ?>)</td>
105
  </tr>
106
-
107
-
108
  <?php if (!empty($link_types)) : ?>
109
-
110
  <?php if ($editable) : ?>
111
-
112
  <tr>
113
  <th<?php if ($link_types_error) echo ' style="color: red;"'; ?>><?php _e('Link types', 'wplnst'); ?></th>
114
  <td class="wplnst-list"><?php foreach ($link_types as $key => $name) : ?><input <?php self::checked($key, $scan->link_types); ?> type="checkbox" name="ck-link-type[<?php echo $key; ?>]" id="ck-link-type-<?php echo $key; ?>" value="on" /><label for="ck-link-type-<?php echo $key; ?>"><?php echo $name; ?></label> &nbsp; <?php endforeach; ?></td>
115
  </tr>
116
-
117
  <?php else : ?>
118
-
119
  <tr>
120
  <th><?php _e('Link types', 'wplnst'); ?></th>
121
  <td class="wplnst-value-list"><?php if (!empty($scan->link_types_names) && is_array($scan->link_types_names)) echo implode(', ', array_map('esc_html', $scan->link_types_names)); ?></td>
122
  </tr>
123
-
124
  <?php endif; ?>
125
-
126
  <?php endif; ?>
127
-
128
-
129
  <?php if (!empty($destination_types)) : ?>
130
-
131
  <?php if ($editable) : ?>
132
-
133
  <tr>
134
  <th><label for="wplnst-destination-type"><?php _e('Destination type', 'wplnst'); ?></label></th>
135
  <td><select id="wplnst-destination-type" name="sl-destination-type"><?php self::options($destination_types, $scan->destination_type); ?></select></td>
136
  </tr>
137
-
138
  <?php else : ?>
139
-
140
  <tr>
141
  <th><?php _e('Destination type', 'wplnst'); ?></th>
142
  <td class="wplnst-value"><?php echo esc_html($scan->destination_type_name); ?></td>
143
  </tr>
144
-
145
  <?php endif; ?>
146
-
147
  <?php endif; ?>
148
-
149
-
150
  <?php if ($editable) : ?>
151
-
152
  <tr>
153
  <th><label for="wplnst-time-scope"><?php _e('Time scope', 'wplnst'); ?></label></th>
154
  <td><select id="wplnst-time-scope" name="sl-time-scope"><?php self::options($time_scopes, $scan->time_scope); ?></select></td>
155
  </tr>
156
-
157
  <?php else : ?>
158
-
159
  <tr>
160
  <th><?php _e('Time scope', 'wplnst'); ?></th>
161
  <td class="wplnst-value"><?php echo esc_html($scan->time_scope_name); ?></td>
162
  </tr>
163
-
164
  <?php endif; ?>
165
-
166
-
167
  <?php if ($editable) : ?>
168
-
169
  <tr>
170
  <th><label for="wplnst-crawl-order"><?php _e('Crawl order', 'wplnst'); ?></label></th>
171
  <td><select id="wplnst-crawl-order" name="sl-crawl-order"><?php self::options($crawl_order, $scan->crawl_order); ?></select></td>
172
  </tr>
173
-
174
  <?php else : ?>
175
-
176
  <tr>
177
  <th><?php _e('Crawl order', 'wplnst'); ?></th>
178
  <td class="wplnst-value"><?php echo esc_html($scan->crawl_order_name); ?></td>
179
  </tr>
180
-
181
  <?php endif; ?>
182
-
183
-
184
  <?php if ($editable) : ?>
185
-
186
  <tr>
187
  <th><?php _e('Redirection status', 'wplnst'); ?></th>
188
  <td class="wplnst-list"><input <?php self::checked($scan->redir_status, true); ?> type="checkbox" id="ck-redir-status" name="ck-redir-status" value="on" /><label for="ck-redir-status"><?php _e('Check status of destination URLs', 'wplnst'); ?></label></td>
189
  </tr>
190
-
191
  <?php else : ?>
192
-
193
  <tr>
194
  <th><?php _e('Redirection status', 'wplnst'); ?></th>
195
  <td class="wplnst-value"><?php echo $scan->redir_status? __('<strong>Yes</strong>, check status of destination URLs', 'wplnst') : __('No check status of destination URLs', 'wplnst'); ?></td>
196
  </tr>
197
-
198
  <?php endif; ?>
199
-
200
-
201
  <?php if ($editable) : ?>
202
-
203
  <tr>
204
  <th><?php _e('Malformed URLs', 'wplnst'); ?></th>
205
  <td class="wplnst-list"><input <?php self::checked($scan->malformed, true); ?> type="checkbox" id="ck-malformed-links" name="ck-malformed-links" value="on" /><label for="ck-malformed-links"><?php _e('Track malformed links', 'wplnst'); ?></label></td>
206
  </tr>
207
-
208
  <?php else : ?>
209
-
210
  <tr>
211
  <th><?php _e('Malformed URLs', 'wplnst'); ?></th>
212
  <td class="wplnst-value"><?php echo $scan->malformed? __('<strong>Yes</strong>, track malformed links', 'wplnst') : __('No tracking of malformed links', 'wplnst'); ?></td>
213
  </tr>
214
-
215
  <?php endif; ?>
216
-
217
-
218
  <?php if ('end' != $scan->status) : ?>
219
-
220
  <tr>
221
  <th><?php _e('Notifications', 'wplnst'); ?></th>
222
  <td class="wplnst-list"><p><?php _e('Send an e-mail when the scan is completed:', 'wplnst'); ?></p>
223
  <p><input <?php self::checked($scan->notify_default, true); ?> type="checkbox" id="ck-notify-default" name="ck-notify-default" value="on" /><label for="ck-notify-default"><?php printf(__('Send to the current blog address <strong>%s</strong>', 'wplnst'), get_option('admin_email'));; ?></label></p>
224
  <p><input <?php self::checked($scan->notify_address, true); ?> type="checkbox" id="ck-notify-address" name="ck-notify-address" value="on" /><label for="ck-notify-address"><?php _e('Send to these e-mail addresses:', 'wplnst'); ?></label><br /><input type="text" name="tx-notify-address-email" id="tx-notify-address-email" value="<?php echo esc_attr($scan->notify_address_email); ?>" class="regular-text" maxlength="255" /></p></td>
225
  </tr>
226
-
227
  <?php endif; ?>
228
-
229
-
230
  </table>
231
-
232
  </div>
233
-
234
-
235
  <div id="wplnst-content" class="wplnst-tab">
236
-
237
  <table class="form-table">
238
-
239
-
240
  <?php if (!empty($post_types)) : ?>
241
-
242
  <?php if ($editable) : ?>
243
-
244
  <tr>
245
  <th<?php if ($post_types_error) echo ' style="color: red;"'; ?>><?php _e('Post types', 'wplnst'); ?></th>
246
  <td class="wplnst-list"><?php foreach ($post_types as $key => $name) : ?><input <?php self::checked($key, $scan->post_types); ?> type="checkbox" name="ck-post-type[<?php echo $key; ?>]" id="ck-post-type-<?php echo $key; ?>" value="on" /><label for="ck-post-type-<?php echo $key; ?>"><?php echo $name; ?> (<code><?php echo $key; ?></code>)</label><br /><?php endforeach; ?></td>
247
  </tr>
248
-
249
  <?php else : ?>
250
-
251
  <tr>
252
  <th><?php _e('Post types', 'wplnst'); ?></th>
253
  <td class="wplnst-value-list"><?php if (empty($scan->post_types_names_strict) || !is_array($scan->post_types_names_strict)) : echo '-'; else : echo implode("<br />", $scan->post_types_names_strict); endif; ?></td>
254
  </tr>
255
-
256
  <?php endif; ?>
257
-
258
  <?php endif; ?>
259
-
260
-
261
  <?php if (!empty($post_status)) : ?>
262
-
263
  <?php if ($editable) : ?>
264
-
265
  <tr>
266
  <th<?php if ($post_status_error) echo ' style="color: red;"'; ?>><?php _e('Post status', 'wplnst'); ?></th>
267
  <td class="wplnst-list"><?php foreach ($post_status as $key) : ?><input <?php self::checked($key, $scan->post_status); ?> type="checkbox" name="ck-post-status[<?php echo $key; ?>]" id="ck-post-status-<?php echo $key; ?>" value="on" /><label for="ck-post-status-<?php echo $key; ?>"><?php echo ucfirst($key); ?></label> &nbsp; <?php endforeach; ?></td>
268
  </tr>
269
-
270
  <?php else : ?>
271
-
272
  <tr>
273
  <th><?php _e('Post status', 'wplnst'); ?></th>
274
  <td class="wplnst-value-list"><?php if (empty($scan->post_status_names) || !is_array($scan->post_status_names)) : echo '-'; else : echo implode(', ', array_map('esc_html', $scan->post_status_names)); endif; ?></td>
275
  </tr>
276
-
277
  <?php endif; ?>
278
-
279
  <?php endif; ?>
280
-
281
  <?php if ($editable) : ?>
282
-
283
  <tr>
284
  <th><label for="wplnst-cf-new"><?php _e('Custom fields', 'wplnst'); ?></label></th>
285
  <td><table id="wplnst-elist-custom-fields" class="wplnst-elist" data-editable="true"></table>
286
  <input type="text" id="wplnst-cf-new" value="" class="regular-text" placeholder="<?php _e('Custom field key', 'wplnst'); ?>" />&nbsp;<select id="wplnst-cf-new-type"><?php self::options($custom_fields, false); ?></select>&nbsp;<input class="button-secondary" type="button" id="wplnst-cf-new-add" value="<?php _e('Add', 'wplnst'); ?>" /></td>
287
  </tr>
288
-
289
  <?php else : ?>
290
-
291
  <tr>
292
  <th><?php _e('Custom fields', 'wplnst'); ?></th>
293
  <td><?php if (empty($scan->custom_fields)) : ?>-<?php else : ?><table id="wplnst-elist-custom-fields" class="wplnst-elist wplnst-elist-readonly" data-editable="false"></table><?php endif; ?></td>
294
  </tr>
295
-
296
  <?php endif; ?>
297
-
298
  <?php if ($editable) : ?>
299
-
300
  <tr>
301
  <th<?php if ($post_types_error) echo ' style="color: red;"'; ?>><?php _e('Comment links', 'wplnst'); ?></th>
302
  <td class="wplnst-list"><?php foreach ($comment_types as $key => $name) : ?><input <?php self::checked($key, $scan->comment_types); ?> type="checkbox" name="ck-comment-type[<?php echo $key; ?>]" id="ck-comment-type-<?php echo $key; ?>" value="on" /><label for="ck-comment-type-<?php echo $key; ?>"><?php echo $name; ?></label> &nbsp; <?php endforeach; ?></td>
303
  </tr>
304
-
305
  <?php else : ?>
306
-
307
  <tr>
308
  <th><?php _e('Comment links', 'wplnst'); ?></th>
309
  <td class="wplnst-value-list"><?php if (!empty($scan->comment_types_names) && is_array($scan->comment_types_names)) echo implode(', ', array_map('esc_html', $scan->comment_types_names)); ?></td>
310
  </tr>
311
-
312
  <?php endif; ?>
313
-
314
  <?php if ($editable) : ?>
315
-
316
  <tr>
317
  <th<?php if ($post_types_error) echo ' style="color: red;"'; ?>><?php _e('Also check links in', 'wplnst'); ?></th>
318
  <td class="wplnst-list"><input <?php self::checked($scan->check_blogroll, true); ?> type="checkbox" name="ck-blogroll" id="ck-blogroll" value="on" /><label for="ck-blogroll"><?php _e('Blogroll links', 'wplnst'); ?></label></td>
319
  </tr>
320
-
321
  <?php else : ?>
322
-
323
  <tr>
324
  <th><?php _e('Also check links in', 'wplnst'); ?></th>
325
  <td class="wplnst-value-list"><?php echo $scan->check_blogroll? __('Blogroll links', 'wplnst') : '-'; ?></td>
326
  </tr>
327
-
328
  <?php endif; ?>
329
  </table>
330
-
331
  </div>
332
-
333
-
334
  <div id="wplnst-filters" class="wplnst-tab">
335
-
336
  <table class="form-table">
337
-
338
  <?php if ($editable) : ?>
339
-
340
  <tr>
341
  <th style="width: 120px;"><?php _e('Anchor filters', 'wplnst'); ?></th>
342
  <td><table id="wplnst-elist-anchor-filters" class="wplnst-elist" cellspacing="0" cellpadding="0" border="0" data-editable="true" data-label="<?php _e('Anchor text', 'wplnst'); ?>"></table>
@@ -344,22 +345,22 @@ class WPLNST_Views_Scans_Edit extends WPLNST_Views {
344
  <input id="wplnst-af-new" type="text" class="regular-text" value="" placeholder="<?php _e('Anchor text filter', 'wplnst'); ?>" />&nbsp;
345
  <input class="button-secondary" type="button" id="wplnst-af-new-add" value="<?php _e('Add', 'wplnst'); ?>" /></td>
346
  </tr>
347
-
348
  <?php else : ?>
349
-
350
  <tr>
351
  <th style="width: 120px;"><?php _e('Anchor filters', 'wplnst'); ?></th>
352
  <td><?php if (empty($scan->anchor_filters)) : ?>-<?php else : ?><table id="wplnst-elist-anchor-filters" class="wplnst-elist wplnst-elist-readonly" cellspacing="0" cellpadding="0" border="0" data-label="<?php _e('Anchor text', 'wplnst'); ?>" data-editable="false"></table><?php endif; ?></td>
353
  </tr>
354
-
355
  <?php endif; ?>
356
-
357
  </table>
358
-
359
  <table class="form-table">
360
-
361
  <?php if ($editable) : ?>
362
-
363
  <tr>
364
  <th style="width: 120px;"><?php _e('Include URLs', 'wplnst'); ?></th>
365
  <td><table id="wplnst-elist-include-urls" class="wplnst-elist" cellspacing="0" cellpadding="0" border="0" data-editable="true"></table>
@@ -367,18 +368,18 @@ class WPLNST_Views_Scans_Edit extends WPLNST_Views {
367
  <select id="wplnst-ius-new-type"><?php self::options($url_filters, false); ?></select>&nbsp;
368
  <input class="button-secondary" type="button" id="wplnst-ius-new-add" value="<?php _e('Add', 'wplnst'); ?>" /></td>
369
  </tr>
370
-
371
  <?php else : ?>
372
-
373
  <tr>
374
  <th style="width: 120px;"><?php _e('Include URLs', 'wplnst'); ?></th>
375
  <td><?php if (empty($scan->include_urls)) : ?>-<?php else : ?><table id="wplnst-elist-include-urls" class="wplnst-elist wplnst-elist-readonly" cellspacing="0" cellpadding="0" border="0" data-editable="false"></table><?php endif; ?></td>
376
  </tr>
377
-
378
  <?php endif; ?>
379
-
380
  <?php if ($editable) : ?>
381
-
382
  <tr>
383
  <th style="width: 120px;"><?php _e('Exclude URLs', 'wplnst'); ?></th>
384
  <td><table id="wplnst-elist-exclude-urls" class="wplnst-elist" cellspacing="0" cellpadding="0" border="0" data-editable="true"></table>
@@ -386,22 +387,22 @@ class WPLNST_Views_Scans_Edit extends WPLNST_Views {
386
  <select id="wplnst-eus-new-type"><?php self::options($url_filters, false); ?></select>&nbsp;
387
  <input class="button-secondary" type="button" id="wplnst-eus-new-add" value="<?php _e('Add', 'wplnst'); ?>" /></td>
388
  </tr>
389
-
390
  <?php else : ?>
391
-
392
  <tr>
393
  <th style="width: 120px;"><?php _e('Exclude URLs', 'wplnst'); ?></th>
394
  <td><?php if (empty($scan->exclude_urls)) : ?>-<?php else : ?><table id="wplnst-elist-exclude-urls" class="wplnst-elist wplnst-elist-readonly" cellspacing="0" cellpadding="0" border="0" data-editable="false"></table><?php endif; ?></td>
395
  </tr>
396
-
397
  <?php endif; ?>
398
-
399
  </table>
400
-
401
  <table class="form-table">
402
-
403
  <?php if ($editable) : ?>
404
-
405
  <tr>
406
  <th style="width: 120px;"><?php _e('HTML attributes', 'wplnst'); ?></th>
407
  <td><table id="wplnst-elist-html-attributes" class="wplnst-elist" cellspacing="0" cellpadding="0" border="0" data-editable="true"></table>
@@ -412,59 +413,59 @@ class WPLNST_Views_Scans_Edit extends WPLNST_Views {
412
  <input id="wplnst-hes-new-val" type="text" class="regular-text" value="" placeholder="<?php _e('Attribute value', 'wplnst'); ?>" style="width: 135px;" />&nbsp;
413
  <input id="wplnst-hes-new-add" class="button-secondary" type="button" value="<?php _e('Add', 'wplnst'); ?>" /></td>
414
  </tr>
415
-
416
  <?php else : ?>
417
-
418
  <tr>
419
  <th style="width: 120px;"><?php _e('HTML attributes', 'wplnst'); ?></th>
420
  <td><?php if (empty($scan->html_attributes)) : ?>-<?php else : ?><table id="wplnst-elist-html-attributes" class="wplnst-elist wplnst-elist-readonly" cellspacing="0" cellpadding="0" border="0" data-editable="false"></table><?php endif; ?></td>
421
  </tr>
422
-
423
  <?php endif; ?>
424
-
425
  </table>
426
-
427
  <table class="form-table">
428
-
429
  <?php $label = __('Accelerate crawling process integrating filters in main database query', 'wplnst'); ?>
430
-
431
  <?php if ($editable) : ?>
432
-
433
  <tr><td><input <?php self::checked($scan->filtered_query, true); ?> type="checkbox" id="wplnst-filtered-query" name="ck-filtered-query" value="on" /><label for="wplnst-filtered-query">&nbsp;<?php echo $label; ?></label></td></tr>
434
-
435
  <?php elseif (!empty($scan->anchor_filters) || !empty($scan->include_urls) || !empty($scan->exclude_urls) || !empty($scan->html_attributes)) : ?>
436
-
437
  <tr><td><?php echo $label; ?>: <strong><?php echo $scan->filtered_query? __('Yes', 'wplnst') : __('No', 'wplnst'); ?></strong></td></tr>
438
-
439
  <?php endif; ?>
440
-
441
  </table>
442
-
443
  </div>
444
-
445
-
446
  <div id="wplnst-status" class="wplnst-tab">
447
-
448
  <table class="form-table">
449
-
450
  <?php if ($editable) : ?>
451
-
452
  <tr>
453
  <th<?php if ($link_status_error) echo ' style="color: red;"'; ?>><?php _e('Track links by level', 'wplnst'); ?></th>
454
  <td class="wplnst-list"><?php foreach ($status_levels as $key => $value) : ?><input <?php self::checked($key, $scan->status_levels); ?> type="checkbox" name="ck-status-level[<?php echo $key; ?>]" id="ck-status-level-<?php echo $key; ?>" class="wplnst-status-level" value="on" /><label for="ck-status-level-<?php echo $key; ?>"><strong><?php echo $key; ?>00s</strong> <?php echo $value; ?></label><br /><?php endforeach; ?></td>
455
  </tr>
456
-
457
  <?php else : ?>
458
-
459
  <tr>
460
  <th><?php _e('Track links by level', 'wplnst'); ?></th>
461
  <td class="wplnst-value-list"><?php if (empty($scan->status_levels_names) || !is_array($scan->status_levels_names)) : echo '-'; else : echo implode("<br />", array_map('esc_html', $scan->status_levels_names)); endif; ?></td>
462
  </tr>
463
-
464
  <?php endif; ?>
465
-
466
  <?php if ($editable) : ?>
467
-
468
  <tr>
469
  <th<?php if ($link_status_error) echo ' style="color: red;"'; ?>><?php _e('Track links by code', 'wplnst'); ?></th>
470
  <td class="wplnst-list"><table cellpadding="0" cellspacing="0" style="margin: 2px 0 0; padding: 0;">
@@ -482,30 +483,30 @@ class WPLNST_Views_Scans_Edit extends WPLNST_Views {
482
  <?php endforeach; ?>
483
  </table></td>
484
  </tr>
485
-
486
  <?php else : ?>
487
-
488
  <tr>
489
  <th><?php _e('Track links by code', 'wplnst'); ?></th>
490
  <td class="wplnst-value-list"><?php if (empty($scan->status_codes_names) || !is_array($scan->status_codes_names)) : echo '-'; else : echo implode("<br />", array_map('esc_html', $scan->status_codes_names)); endif; ?></td>
491
  </tr>
492
-
493
  <?php endif; ?>
494
-
495
  </table>
496
-
497
  </div>
498
-
499
-
500
  <?php if (false) : ?><div id="wplnst-scheduled" class="wplnst-tab">
501
-
502
  </div><?php endif; ?>
503
-
504
-
505
  <div id="wplnst-advanced" class="wplnst-tab">
506
-
507
  <?php if ('end' == $scan->status) : ?>
508
-
509
  <table class="form-table">
510
  <tr>
511
  <th><?php _e('Number of threads', 'wplnst'); ?></th>
@@ -520,11 +521,11 @@ class WPLNST_Views_Scans_Edit extends WPLNST_Views {
520
  <td class="wplnst-value"><?php echo empty($scan->threads->request_timeout)? '-' : esc_html($scan->threads->request_timeout).' '.__('seconds', 'wplnst'); ?></td>
521
  </tr>
522
  </table>
523
-
524
  <?php else : ?>
525
-
526
  <p><?php _e('All these values are optional, leave them empty to use plugin defaults.', 'wplnst'); ?></p>
527
-
528
  <table class="form-table">
529
  <tr>
530
  <th><label for="tx-threads"><?php _e('Number of threads', 'wplnst'); ?></label></th>
@@ -539,18 +540,18 @@ class WPLNST_Views_Scans_Edit extends WPLNST_Views {
539
  <td><input type="text" name="tx-request-timeout" id="tx-request-timeout" value="<?php echo empty($scan->threads->request_timeout)? '' : esc_attr($scan->threads->request_timeout); ?>" class="small-text" /> <?php _e('seconds', 'wplnst'); ?> <?php printf(__('(optional, default %d seconds)', 'wplnst'), $default_request_timeout); ?></td>
540
  </tr>
541
  </table>
542
-
543
  <?php endif; ?>
544
-
545
  </div>
546
-
547
-
548
  <p><input type="submit" value="<?php _e('Save scan changes', 'wplnst'); ?>" class="button button-primary" />
549
  <?php if ($is_ready && ('wait' == $scan->status)) : ?> &nbsp; <input id="wplnst-save-and-run" type="button" value="<?php _e('Save and run crawler', 'wplnst'); ?>" class="button" /><?php endif; ?>
550
  <?php if ($scan->id > 0) : ?> &nbsp;&nbsp; <a href="<?php echo esc_url(WPLNST_Core_Plugin::get_url_scans_delete($scan->id, $scan->hash)); ?>" class="wplnst-scan-delete-isolated wplnst-trash-editor" data-confirm-delete="<?php echo esc_attr(WPLNST_Admin::get_text('scan_delete_confirm')); ?>"><?php _e('Delete this scan', 'wplnst'); ?></a><?php endif; ?></p>
551
-
552
  </div>
553
-
554
  </form><?php
555
  }
556
 
1
  <?php
2
 
3
  // Load views class
4
+ require_once dirname(__FILE__).'/views.php';
5
 
6
  /**
7
+ * Scans Edit class
8
  *
9
  * @package WP Link Status
10
+ * @subpackage Views
11
  */
12
  class WPLNST_Views_Scans_Edit extends WPLNST_Views {
13
 
17
  * Show scan edit form
18
  */
19
  public static function view($args) {
20
+
21
  // Vars
22
  extract($args);
23
+
24
  // Initialize
25
  $is_ready = true;
26
  $editable = ('wait' == $scan->status);
27
+
28
  // Check errors
29
  $link_types_error = $post_types_error = $post_status_error = $link_status_error = false;
30
  if (!empty($notice_ready) && is_array($notice_ready)) {
31
+
32
  // Inside form errors
33
  $link_types_error = isset($notice_ready['link_types']);
34
  $post_types_error = isset($notice_ready['post_types']);
35
  $post_status_error = isset($notice_ready['post_status']);
36
  $link_status_error = isset($notice_ready['link_status']);
37
+
38
  // Determine if ready
39
  $is_ready = !($link_types_error || $post_types_error || $post_status_error || $link_status_error);
40
+
41
  // Show notice errors
42
  echo '<div class="error notice">';
43
+ foreach ($notice_ready as $notice_key => $notice_title) {
44
  echo '<p>'.$notice_title.'</p>';
45
+ }
46
  echo '</div>';
47
  } ?>
48
+
49
  <?php if ($is_ready && $scan->id > 0) :
50
+
51
  // Prepare URLs
52
  $results_url = esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan->id));
53
  $start_url = esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($scan->id, 'on', $scan->hash));
54
  $stop_url = esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($scan->id, 'off', $scan->hash)); ?>
55
+
56
  <?php if ('stop' == $scan->status) : ?>
57
+
58
  <div class="notice"><p><?php printf(__('The crawler for this scan is <strong>stopped</strong> but you can see the <a href="%s">crawling results</a> collected data.', 'wplnst'), $results_url); if ($more_scans) : echo ' '; printf(__('Or you can <a href="%s">start again the crawler</a>.', 'wplnst'), $start_url); endif; ?></p></div>
59
+
60
  <?php elseif ('play' == $scan->status) : ?>
61
+
62
  <?php if (empty($_POST['scan_run']) && empty($_GET['started'])) : ?>
63
+
64
  <div class="notice"><p><?php printf(__('The crawler for this scan is <strong>running</strong> and you can see its <a href="%s">crawling results data</a>.', 'wplnst'), $results_url); echo ' '; printf(__('If needed you can <a href="%s">stop the crawler</a>.', 'wplnst'), $stop_url); ?></p></div>
65
+
66
  <?php endif; ?>
67
+
68
  <?php elseif ('end' == $scan->status) : ?>
69
+
70
  <div class="notice"><p><?php printf(__('The crawler is completed and you can see all its <a href="%s">crawling results</a>.', 'wplnst'), $results_url); ?></p></div>
71
+
72
  <?php endif; ?>
73
+
74
  <?php endif; ?>
75
+
76
  <form method="post" id="wplnst-form" action="<?php echo esc_url($action); ?>">
77
+
78
  <input type="hidden" name="scan_id" id="wplnst-scan-id" value="<?php echo esc_attr($scan->id); ?>" />
79
  <input type="hidden" name="scan_run" id="wplnst-scan-run" value="" />
80
  <input type="hidden" name="scan_edit_nonce" value="<?php echo esc_attr($nonce); ?>" />
81
+
82
  <input type="hidden" name="scan_custom_fields" id="wplnst-scan-custom-fields" value='<?php echo self::esc_attr_elist($scan->custom_fields); ?>' />
83
  <input type="hidden" name="scan_anchor_filters" id="wplnst-scan-anchor-filters" value='<?php echo self::esc_attr_elist($scan->anchor_filters); ?>' />
84
  <input type="hidden" name="scan_include_urls" id="wplnst-scan-include-urls" value='<?php echo self::esc_attr_elist($scan->include_urls); ?>' />
85
  <input type="hidden" name="scan_exclude_urls" id="wplnst-scan-exclude-urls" value='<?php echo self::esc_attr_elist($scan->exclude_urls); ?>' />
86
  <input type="hidden" name="scan_html_attributes" id="wplnst-scan-html-attributes" value='<?php echo self::esc_attr_elist($scan->html_attributes); ?>' />
87
+
88
  <h2 id="wplnst-tabs-nav" class="nav-tab-wrapper">
89
  <a id="wplnst-general-tab" href="#top#wplnst-general" class="nav-tab"<?php if ($link_types_error) echo ' style="color: red;"'; ?>><?php _e('General', 'wplnst'); ?></a>
90
  <a id="wplnst-content-tab" href="#top#wplnst-content" class="nav-tab"<?php if ($post_types_error || $post_status_error) echo ' style="color: red;"'; ?>><?php _e('Content options', 'wplnst'); ?></a>
93
  <?php if (false) : ?><a id="wplnst-scheduled-tab" href="#top#wplnst-scheduled" class="nav-tab"><?php _e('Schedule', 'wplnst'); ?></a><?php endif; ?>
94
  <a id="wplnst-advanced-tab" href="#top#wplnst-advanced" class="nav-tab"><?php _e('Advanced', 'wplnst'); ?></a>
95
  </h2>
96
+
97
  <div id="wplnst-tabs" class="wplnst-tabs-scan-edit">
98
+
99
  <div id="wplnst-general" class="wplnst-tab wplnst-tab-default">
100
+
101
  <table class="form-table">
102
+
103
  <tr>
104
  <th><label for="tx-name"><?php _e('Scan name', 'wplnst'); ?></label></th>
105
  <td><input type="text" name="tx-name" id="tx-name" value="<?php echo esc_attr($scan->name); ?>" class="regular-text" maxlength="255" /> (<?php _e('optional', 'wplnst'); ?>)</td>
106
  </tr>
107
+
108
+
109
  <?php if (!empty($link_types)) : ?>
110
+
111
  <?php if ($editable) : ?>
112
+
113
  <tr>
114
  <th<?php if ($link_types_error) echo ' style="color: red;"'; ?>><?php _e('Link types', 'wplnst'); ?></th>
115
  <td class="wplnst-list"><?php foreach ($link_types as $key => $name) : ?><input <?php self::checked($key, $scan->link_types); ?> type="checkbox" name="ck-link-type[<?php echo $key; ?>]" id="ck-link-type-<?php echo $key; ?>" value="on" /><label for="ck-link-type-<?php echo $key; ?>"><?php echo $name; ?></label> &nbsp; <?php endforeach; ?></td>
116
  </tr>
117
+
118
  <?php else : ?>
119
+
120
  <tr>
121
  <th><?php _e('Link types', 'wplnst'); ?></th>
122
  <td class="wplnst-value-list"><?php if (!empty($scan->link_types_names) && is_array($scan->link_types_names)) echo implode(', ', array_map('esc_html', $scan->link_types_names)); ?></td>
123
  </tr>
124
+
125
  <?php endif; ?>
126
+
127
  <?php endif; ?>
128
+
129
+
130
  <?php if (!empty($destination_types)) : ?>
131
+
132
  <?php if ($editable) : ?>
133
+
134
  <tr>
135
  <th><label for="wplnst-destination-type"><?php _e('Destination type', 'wplnst'); ?></label></th>
136
  <td><select id="wplnst-destination-type" name="sl-destination-type"><?php self::options($destination_types, $scan->destination_type); ?></select></td>
137
  </tr>
138
+
139
  <?php else : ?>
140
+
141
  <tr>
142
  <th><?php _e('Destination type', 'wplnst'); ?></th>
143
  <td class="wplnst-value"><?php echo esc_html($scan->destination_type_name); ?></td>
144
  </tr>
145
+
146
  <?php endif; ?>
147
+
148
  <?php endif; ?>
149
+
150
+
151
  <?php if ($editable) : ?>
152
+
153
  <tr>
154
  <th><label for="wplnst-time-scope"><?php _e('Time scope', 'wplnst'); ?></label></th>
155
  <td><select id="wplnst-time-scope" name="sl-time-scope"><?php self::options($time_scopes, $scan->time_scope); ?></select></td>
156
  </tr>
157
+
158
  <?php else : ?>
159
+
160
  <tr>
161
  <th><?php _e('Time scope', 'wplnst'); ?></th>
162
  <td class="wplnst-value"><?php echo esc_html($scan->time_scope_name); ?></td>
163
  </tr>
164
+
165
  <?php endif; ?>
166
+
167
+
168
  <?php if ($editable) : ?>
169
+
170
  <tr>
171
  <th><label for="wplnst-crawl-order"><?php _e('Crawl order', 'wplnst'); ?></label></th>
172
  <td><select id="wplnst-crawl-order" name="sl-crawl-order"><?php self::options($crawl_order, $scan->crawl_order); ?></select></td>
173
  </tr>
174
+
175
  <?php else : ?>
176
+
177
  <tr>
178
  <th><?php _e('Crawl order', 'wplnst'); ?></th>
179
  <td class="wplnst-value"><?php echo esc_html($scan->crawl_order_name); ?></td>
180
  </tr>
181
+
182
  <?php endif; ?>
183
+
184
+
185
  <?php if ($editable) : ?>
186
+
187
  <tr>
188
  <th><?php _e('Redirection status', 'wplnst'); ?></th>
189
  <td class="wplnst-list"><input <?php self::checked($scan->redir_status, true); ?> type="checkbox" id="ck-redir-status" name="ck-redir-status" value="on" /><label for="ck-redir-status"><?php _e('Check status of destination URLs', 'wplnst'); ?></label></td>
190
  </tr>
191
+
192
  <?php else : ?>
193
+
194
  <tr>
195
  <th><?php _e('Redirection status', 'wplnst'); ?></th>
196
  <td class="wplnst-value"><?php echo $scan->redir_status? __('<strong>Yes</strong>, check status of destination URLs', 'wplnst') : __('No check status of destination URLs', 'wplnst'); ?></td>
197
  </tr>
198
+
199
  <?php endif; ?>
200
+
201
+
202
  <?php if ($editable) : ?>
203
+
204
  <tr>
205
  <th><?php _e('Malformed URLs', 'wplnst'); ?></th>
206
  <td class="wplnst-list"><input <?php self::checked($scan->malformed, true); ?> type="checkbox" id="ck-malformed-links" name="ck-malformed-links" value="on" /><label for="ck-malformed-links"><?php _e('Track malformed links', 'wplnst'); ?></label></td>
207
  </tr>
208
+
209
  <?php else : ?>
210
+
211
  <tr>
212
  <th><?php _e('Malformed URLs', 'wplnst'); ?></th>
213
  <td class="wplnst-value"><?php echo $scan->malformed? __('<strong>Yes</strong>, track malformed links', 'wplnst') : __('No tracking of malformed links', 'wplnst'); ?></td>
214
  </tr>
215
+
216
  <?php endif; ?>
217
+
218
+
219
  <?php if ('end' != $scan->status) : ?>
220
+
221
  <tr>
222
  <th><?php _e('Notifications', 'wplnst'); ?></th>
223
  <td class="wplnst-list"><p><?php _e('Send an e-mail when the scan is completed:', 'wplnst'); ?></p>
224
  <p><input <?php self::checked($scan->notify_default, true); ?> type="checkbox" id="ck-notify-default" name="ck-notify-default" value="on" /><label for="ck-notify-default"><?php printf(__('Send to the current blog address <strong>%s</strong>', 'wplnst'), get_option('admin_email'));; ?></label></p>
225
  <p><input <?php self::checked($scan->notify_address, true); ?> type="checkbox" id="ck-notify-address" name="ck-notify-address" value="on" /><label for="ck-notify-address"><?php _e('Send to these e-mail addresses:', 'wplnst'); ?></label><br /><input type="text" name="tx-notify-address-email" id="tx-notify-address-email" value="<?php echo esc_attr($scan->notify_address_email); ?>" class="regular-text" maxlength="255" /></p></td>
226
  </tr>
227
+
228
  <?php endif; ?>
229
+
230
+
231
  </table>
232
+
233
  </div>
234
+
235
+
236
  <div id="wplnst-content" class="wplnst-tab">
237
+
238
  <table class="form-table">
239
+
240
+
241
  <?php if (!empty($post_types)) : ?>
242
+
243
  <?php if ($editable) : ?>
244
+
245
  <tr>
246
  <th<?php if ($post_types_error) echo ' style="color: red;"'; ?>><?php _e('Post types', 'wplnst'); ?></th>
247
  <td class="wplnst-list"><?php foreach ($post_types as $key => $name) : ?><input <?php self::checked($key, $scan->post_types); ?> type="checkbox" name="ck-post-type[<?php echo $key; ?>]" id="ck-post-type-<?php echo $key; ?>" value="on" /><label for="ck-post-type-<?php echo $key; ?>"><?php echo $name; ?> (<code><?php echo $key; ?></code>)</label><br /><?php endforeach; ?></td>
248
  </tr>
249
+
250
  <?php else : ?>
251
+
252
  <tr>
253
  <th><?php _e('Post types', 'wplnst'); ?></th>
254
  <td class="wplnst-value-list"><?php if (empty($scan->post_types_names_strict) || !is_array($scan->post_types_names_strict)) : echo '-'; else : echo implode("<br />", $scan->post_types_names_strict); endif; ?></td>
255
  </tr>
256
+
257
  <?php endif; ?>
258
+
259
  <?php endif; ?>
260
+
261
+
262
  <?php if (!empty($post_status)) : ?>
263
+
264
  <?php if ($editable) : ?>
265
+
266
  <tr>
267
  <th<?php if ($post_status_error) echo ' style="color: red;"'; ?>><?php _e('Post status', 'wplnst'); ?></th>
268
  <td class="wplnst-list"><?php foreach ($post_status as $key) : ?><input <?php self::checked($key, $scan->post_status); ?> type="checkbox" name="ck-post-status[<?php echo $key; ?>]" id="ck-post-status-<?php echo $key; ?>" value="on" /><label for="ck-post-status-<?php echo $key; ?>"><?php echo ucfirst($key); ?></label> &nbsp; <?php endforeach; ?></td>
269
  </tr>
270
+
271
  <?php else : ?>
272
+
273
  <tr>
274
  <th><?php _e('Post status', 'wplnst'); ?></th>
275
  <td class="wplnst-value-list"><?php if (empty($scan->post_status_names) || !is_array($scan->post_status_names)) : echo '-'; else : echo implode(', ', array_map('esc_html', $scan->post_status_names)); endif; ?></td>
276
  </tr>
277
+
278
  <?php endif; ?>
279
+
280
  <?php endif; ?>
281
+
282
  <?php if ($editable) : ?>
283
+
284
  <tr>
285
  <th><label for="wplnst-cf-new"><?php _e('Custom fields', 'wplnst'); ?></label></th>
286
  <td><table id="wplnst-elist-custom-fields" class="wplnst-elist" data-editable="true"></table>
287
  <input type="text" id="wplnst-cf-new" value="" class="regular-text" placeholder="<?php _e('Custom field key', 'wplnst'); ?>" />&nbsp;<select id="wplnst-cf-new-type"><?php self::options($custom_fields, false); ?></select>&nbsp;<input class="button-secondary" type="button" id="wplnst-cf-new-add" value="<?php _e('Add', 'wplnst'); ?>" /></td>
288
  </tr>
289
+
290
  <?php else : ?>
291
+
292
  <tr>
293
  <th><?php _e('Custom fields', 'wplnst'); ?></th>
294
  <td><?php if (empty($scan->custom_fields)) : ?>-<?php else : ?><table id="wplnst-elist-custom-fields" class="wplnst-elist wplnst-elist-readonly" data-editable="false"></table><?php endif; ?></td>
295
  </tr>
296
+
297
  <?php endif; ?>
298
+
299
  <?php if ($editable) : ?>
300
+
301
  <tr>
302
  <th<?php if ($post_types_error) echo ' style="color: red;"'; ?>><?php _e('Comment links', 'wplnst'); ?></th>
303
  <td class="wplnst-list"><?php foreach ($comment_types as $key => $name) : ?><input <?php self::checked($key, $scan->comment_types); ?> type="checkbox" name="ck-comment-type[<?php echo $key; ?>]" id="ck-comment-type-<?php echo $key; ?>" value="on" /><label for="ck-comment-type-<?php echo $key; ?>"><?php echo $name; ?></label> &nbsp; <?php endforeach; ?></td>
304
  </tr>
305
+
306
  <?php else : ?>
307
+
308
  <tr>
309
  <th><?php _e('Comment links', 'wplnst'); ?></th>
310
  <td class="wplnst-value-list"><?php if (!empty($scan->comment_types_names) && is_array($scan->comment_types_names)) echo implode(', ', array_map('esc_html', $scan->comment_types_names)); ?></td>
311
  </tr>
312
+
313
  <?php endif; ?>
314
+
315
  <?php if ($editable) : ?>
316
+
317
  <tr>
318
  <th<?php if ($post_types_error) echo ' style="color: red;"'; ?>><?php _e('Also check links in', 'wplnst'); ?></th>
319
  <td class="wplnst-list"><input <?php self::checked($scan->check_blogroll, true); ?> type="checkbox" name="ck-blogroll" id="ck-blogroll" value="on" /><label for="ck-blogroll"><?php _e('Blogroll links', 'wplnst'); ?></label></td>
320
  </tr>
321
+
322
  <?php else : ?>
323
+
324
  <tr>
325
  <th><?php _e('Also check links in', 'wplnst'); ?></th>
326
  <td class="wplnst-value-list"><?php echo $scan->check_blogroll? __('Blogroll links', 'wplnst') : '-'; ?></td>
327
  </tr>
328
+
329
  <?php endif; ?>
330
  </table>
331
+
332
  </div>
333
+
334
+
335
  <div id="wplnst-filters" class="wplnst-tab">
336
+
337
  <table class="form-table">
338
+
339
  <?php if ($editable) : ?>
340
+
341
  <tr>
342
  <th style="width: 120px;"><?php _e('Anchor filters', 'wplnst'); ?></th>
343
  <td><table id="wplnst-elist-anchor-filters" class="wplnst-elist" cellspacing="0" cellpadding="0" border="0" data-editable="true" data-label="<?php _e('Anchor text', 'wplnst'); ?>"></table>
345
  <input id="wplnst-af-new" type="text" class="regular-text" value="" placeholder="<?php _e('Anchor text filter', 'wplnst'); ?>" />&nbsp;
346
  <input class="button-secondary" type="button" id="wplnst-af-new-add" value="<?php _e('Add', 'wplnst'); ?>" /></td>
347
  </tr>
348
+
349
  <?php else : ?>
350
+
351
  <tr>
352
  <th style="width: 120px;"><?php _e('Anchor filters', 'wplnst'); ?></th>
353
  <td><?php if (empty($scan->anchor_filters)) : ?>-<?php else : ?><table id="wplnst-elist-anchor-filters" class="wplnst-elist wplnst-elist-readonly" cellspacing="0" cellpadding="0" border="0" data-label="<?php _e('Anchor text', 'wplnst'); ?>" data-editable="false"></table><?php endif; ?></td>
354
  </tr>
355
+
356
  <?php endif; ?>
357
+
358
  </table>
359
+
360
  <table class="form-table">
361
+
362
  <?php if ($editable) : ?>
363
+
364
  <tr>
365
  <th style="width: 120px;"><?php _e('Include URLs', 'wplnst'); ?></th>
366
  <td><table id="wplnst-elist-include-urls" class="wplnst-elist" cellspacing="0" cellpadding="0" border="0" data-editable="true"></table>
368
  <select id="wplnst-ius-new-type"><?php self::options($url_filters, false); ?></select>&nbsp;
369
  <input class="button-secondary" type="button" id="wplnst-ius-new-add" value="<?php _e('Add', 'wplnst'); ?>" /></td>
370
  </tr>
371
+
372
  <?php else : ?>
373
+
374
  <tr>
375
  <th style="width: 120px;"><?php _e('Include URLs', 'wplnst'); ?></th>
376
  <td><?php if (empty($scan->include_urls)) : ?>-<?php else : ?><table id="wplnst-elist-include-urls" class="wplnst-elist wplnst-elist-readonly" cellspacing="0" cellpadding="0" border="0" data-editable="false"></table><?php endif; ?></td>
377
  </tr>
378
+
379
  <?php endif; ?>
380
+
381
  <?php if ($editable) : ?>
382
+
383
  <tr>
384
  <th style="width: 120px;"><?php _e('Exclude URLs', 'wplnst'); ?></th>
385
  <td><table id="wplnst-elist-exclude-urls" class="wplnst-elist" cellspacing="0" cellpadding="0" border="0" data-editable="true"></table>
387
  <select id="wplnst-eus-new-type"><?php self::options($url_filters, false); ?></select>&nbsp;
388
  <input class="button-secondary" type="button" id="wplnst-eus-new-add" value="<?php _e('Add', 'wplnst'); ?>" /></td>
389
  </tr>
390
+
391
  <?php else : ?>
392
+
393
  <tr>
394
  <th style="width: 120px;"><?php _e('Exclude URLs', 'wplnst'); ?></th>
395
  <td><?php if (empty($scan->exclude_urls)) : ?>-<?php else : ?><table id="wplnst-elist-exclude-urls" class="wplnst-elist wplnst-elist-readonly" cellspacing="0" cellpadding="0" border="0" data-editable="false"></table><?php endif; ?></td>
396
  </tr>
397
+
398
  <?php endif; ?>
399
+
400
  </table>
401
+
402
  <table class="form-table">
403
+
404
  <?php if ($editable) : ?>
405
+
406
  <tr>
407
  <th style="width: 120px;"><?php _e('HTML attributes', 'wplnst'); ?></th>
408
  <td><table id="wplnst-elist-html-attributes" class="wplnst-elist" cellspacing="0" cellpadding="0" border="0" data-editable="true"></table>
413
  <input id="wplnst-hes-new-val" type="text" class="regular-text" value="" placeholder="<?php _e('Attribute value', 'wplnst'); ?>" style="width: 135px;" />&nbsp;
414
  <input id="wplnst-hes-new-add" class="button-secondary" type="button" value="<?php _e('Add', 'wplnst'); ?>" /></td>
415
  </tr>
416
+
417
  <?php else : ?>
418
+
419
  <tr>
420
  <th style="width: 120px;"><?php _e('HTML attributes', 'wplnst'); ?></th>
421
  <td><?php if (empty($scan->html_attributes)) : ?>-<?php else : ?><table id="wplnst-elist-html-attributes" class="wplnst-elist wplnst-elist-readonly" cellspacing="0" cellpadding="0" border="0" data-editable="false"></table><?php endif; ?></td>
422
  </tr>
423
+
424
  <?php endif; ?>
425
+
426
  </table>
427
+
428
  <table class="form-table">
429
+
430
  <?php $label = __('Accelerate crawling process integrating filters in main database query', 'wplnst'); ?>
431
+
432
  <?php if ($editable) : ?>
433
+
434
  <tr><td><input <?php self::checked($scan->filtered_query, true); ?> type="checkbox" id="wplnst-filtered-query" name="ck-filtered-query" value="on" /><label for="wplnst-filtered-query">&nbsp;<?php echo $label; ?></label></td></tr>
435
+
436
  <?php elseif (!empty($scan->anchor_filters) || !empty($scan->include_urls) || !empty($scan->exclude_urls) || !empty($scan->html_attributes)) : ?>
437
+
438
  <tr><td><?php echo $label; ?>: <strong><?php echo $scan->filtered_query? __('Yes', 'wplnst') : __('No', 'wplnst'); ?></strong></td></tr>
439
+
440
  <?php endif; ?>
441
+
442
  </table>
443
+
444
  </div>
445
+
446
+
447
  <div id="wplnst-status" class="wplnst-tab">
448
+
449
  <table class="form-table">
450
+
451
  <?php if ($editable) : ?>
452
+
453
  <tr>
454
  <th<?php if ($link_status_error) echo ' style="color: red;"'; ?>><?php _e('Track links by level', 'wplnst'); ?></th>
455
  <td class="wplnst-list"><?php foreach ($status_levels as $key => $value) : ?><input <?php self::checked($key, $scan->status_levels); ?> type="checkbox" name="ck-status-level[<?php echo $key; ?>]" id="ck-status-level-<?php echo $key; ?>" class="wplnst-status-level" value="on" /><label for="ck-status-level-<?php echo $key; ?>"><strong><?php echo $key; ?>00s</strong> <?php echo $value; ?></label><br /><?php endforeach; ?></td>
456
  </tr>
457
+
458
  <?php else : ?>
459
+
460
  <tr>
461
  <th><?php _e('Track links by level', 'wplnst'); ?></th>
462
  <td class="wplnst-value-list"><?php if (empty($scan->status_levels_names) || !is_array($scan->status_levels_names)) : echo '-'; else : echo implode("<br />", array_map('esc_html', $scan->status_levels_names)); endif; ?></td>
463
  </tr>
464
+
465
  <?php endif; ?>
466
+
467
  <?php if ($editable) : ?>
468
+
469
  <tr>
470
  <th<?php if ($link_status_error) echo ' style="color: red;"'; ?>><?php _e('Track links by code', 'wplnst'); ?></th>
471
  <td class="wplnst-list"><table cellpadding="0" cellspacing="0" style="margin: 2px 0 0; padding: 0;">
483
  <?php endforeach; ?>
484
  </table></td>
485
  </tr>
486
+
487
  <?php else : ?>
488
+
489
  <tr>
490
  <th><?php _e('Track links by code', 'wplnst'); ?></th>
491
  <td class="wplnst-value-list"><?php if (empty($scan->status_codes_names) || !is_array($scan->status_codes_names)) : echo '-'; else : echo implode("<br />", array_map('esc_html', $scan->status_codes_names)); endif; ?></td>
492
  </tr>
493
+
494
  <?php endif; ?>
495
+
496
  </table>
497
+
498
  </div>
499
+
500
+
501
  <?php if (false) : ?><div id="wplnst-scheduled" class="wplnst-tab">
502
+
503
  </div><?php endif; ?>
504
+
505
+
506
  <div id="wplnst-advanced" class="wplnst-tab">
507
+
508
  <?php if ('end' == $scan->status) : ?>
509
+
510
  <table class="form-table">
511
  <tr>
512
  <th><?php _e('Number of threads', 'wplnst'); ?></th>
521
  <td class="wplnst-value"><?php echo empty($scan->threads->request_timeout)? '-' : esc_html($scan->threads->request_timeout).' '.__('seconds', 'wplnst'); ?></td>
522
  </tr>
523
  </table>
524
+
525
  <?php else : ?>
526
+
527
  <p><?php _e('All these values are optional, leave them empty to use plugin defaults.', 'wplnst'); ?></p>
528
+
529
  <table class="form-table">
530
  <tr>
531
  <th><label for="tx-threads"><?php _e('Number of threads', 'wplnst'); ?></label></th>
540
  <td><input type="text" name="tx-request-timeout" id="tx-request-timeout" value="<?php echo empty($scan->threads->request_timeout)? '' : esc_attr($scan->threads->request_timeout); ?>" class="small-text" /> <?php _e('seconds', 'wplnst'); ?> <?php printf(__('(optional, default %d seconds)', 'wplnst'), $default_request_timeout); ?></td>
541
  </tr>
542
  </table>
543
+
544
  <?php endif; ?>
545
+
546
  </div>
547
+
548
+
549
  <p><input type="submit" value="<?php _e('Save scan changes', 'wplnst'); ?>" class="button button-primary" />
550
  <?php if ($is_ready && ('wait' == $scan->status)) : ?> &nbsp; <input id="wplnst-save-and-run" type="button" value="<?php _e('Save and run crawler', 'wplnst'); ?>" class="button" /><?php endif; ?>
551
  <?php if ($scan->id > 0) : ?> &nbsp;&nbsp; <a href="<?php echo esc_url(WPLNST_Core_Plugin::get_url_scans_delete($scan->id, $scan->hash)); ?>" class="wplnst-scan-delete-isolated wplnst-trash-editor" data-confirm-delete="<?php echo esc_attr(WPLNST_Admin::get_text('scan_delete_confirm')); ?>"><?php _e('Delete this scan', 'wplnst'); ?></a><?php endif; ?></p>
552
+
553
  </div>
554
+
555
  </form><?php
556
  }
557
 
views/scans-results.php CHANGED
@@ -1,18 +1,20 @@
1
  <?php
2
 
3
  // Check WP constant
4
- if (!defined('ABSPATH'))
5
  die;
 
6
 
7
  // Check dependencies
8
- if(!class_exists('WP_List_Table'))
9
- require_once(ABSPATH.'wp-admin/includes/class-wp-list-table.php');
 
10
 
11
  /**
12
- * WP Link Status Views Scans Results class
13
  *
14
  * @package WP Link Status
15
- * @subpackage WP Link Status Views
16
  */
17
  class WPLNST_Views_Scans_Results extends WP_List_Table {
18
 
@@ -46,17 +48,17 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
46
  * Constructor
47
  */
48
  public function __construct($results) {
49
-
50
  // Dependencies
51
  wplnst_require('core', 'util-math');
52
  wplnst_require('core', 'util-string');
53
-
54
  // Parent constructor
55
  parent::__construct();
56
-
57
  // Copy results
58
  $this->results = $results;
59
-
60
  // Base link for filters
61
  $this->base_url = esc_url(WPLNST_Core_Plugin::get_url_scans_results($this->results->scan->id));
62
  }
@@ -72,13 +74,13 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
72
  * Prepare columns and data
73
  */
74
  function prepare_items() {
75
-
76
  // Columns
77
  $this->setup_columns();
78
-
79
  // Data items
80
  $this->setup_items();
81
-
82
  // Pagination
83
  $this->setup_pagination();
84
  }
@@ -89,11 +91,11 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
89
  * Setup columns
90
  */
91
  private function setup_columns() {
92
-
93
  // Initialize
94
  $hidden = array();
95
  $sortable = array();
96
-
97
  // Column headers
98
  $this->_column_headers = array($this->get_columns(), $hidden, $sortable);
99
  }
@@ -104,7 +106,7 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
104
  * Columns array
105
  */
106
  public function get_columns(){
107
-
108
  // Prepare
109
  $columns = array(
110
  'cb' => '<input type="checkbox" />',
@@ -113,7 +115,7 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
113
  'wplnst-anchor' => __('Anchor text', 'wplnst'),
114
  'wplnst-content' => __('Content', 'wplnst'),
115
  );
116
-
117
  // Exception
118
  if ($this->results->isolated) {
119
  unset($columns['cb']);
@@ -121,7 +123,7 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
121
  } elseif (!$this->get_columns_cb()) {
122
  unset($columns['cb']);
123
  }
124
-
125
  // Done
126
  return $columns;
127
  }
@@ -141,19 +143,19 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
141
  * Setup data items
142
  */
143
  private function setup_items() {
144
-
145
  // Dependencies
146
  wplnst_require('core', 'types-curl');
147
-
148
  // Initialize
149
  $status_levels = WPLNST_Core_Types::get_status_levels();
150
  $status_codes = WPLNST_Core_Types::get_status_codes_raw();
151
-
152
  // Populate data
153
  $this->items = array();
154
  foreach ($this->results->rows as $row) {
155
-
156
-
157
  // Normalize identifier
158
  $item = array(
159
  'ID' => $row->url_id,
@@ -173,92 +175,97 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
173
  'anchored' => $row->anchored,
174
  'attributed' => $row->attributed,
175
  );
176
-
177
-
178
  /* First column: URL */
179
-
180
-
181
  // Add unlinked flag
182
  $url = '<span id="wplnst-results-url-unlinked-'.$row->loc_id.'" class="wplnst-results-mark wplnst-results-mark-unlinked'.($row->unlinked? '' : ' wplnst-display-none').'">'.__('Unlinked', 'wplnst').'</span>';
183
-
184
  // Check link
185
  if ('http' == $row->scheme || 'https' == $row->scheme || 'ftp' == $row->scheme) {
186
-
187
  // Link to an browser resource
188
  $url .= '<strong><a href="'.esc_url($row->url).'" target="_blank" id="wplnst-results-url-loc-'.$row->loc_id.'" title="'.esc_url($row->url).'">'.esc_html($row->raw_url).'</a></strong>';
189
-
190
  // No link
191
  } else {
192
-
193
  // Unsupported linkable protocol
194
  $url .= '<strong><span id="wplnst-results-url-loc-'.$row->loc_id.'">'.esc_html($row->raw_url).'</span></strong>';
195
  }
196
-
197
-
198
  // Redirection
199
  $class_redirection = ('3' == $row->status_level && $row->redirect_url_id > 0 && !empty($row->redirect_url))? '' : 'wplnst-display-none';
200
  $url .= '<span id="wplnst-results-url-redir-'.$row->loc_id.'" class="'.$class_redirection.'"><br />&rarr;&nbsp;<a id="wplnst-results-url-redir-href-'.$row->loc_id.'" href="'.esc_url($row->redirect_url).'" target="_blank">'.esc_html($row->redirect_url).'</a></span>';
201
-
202
-
203
  // Check error
204
  $class_error = (!empty($row->status_code) || empty($row->curl_errno))? 'wplnst-display-none' : '';
205
  $url .= '<div id="wplnst-results-url-error-'.$row->loc_id.'" class="'.$class_error.'">';
206
  if (empty($row->status_code) && !empty($row->curl_errno)) {
207
-
208
  // Retrieve error type
209
  $curl_error = WPLNST_Core_Types_CURL::get_code_info($row->curl_errno);
210
-
211
  // Unknown
212
  if (empty($curl_error)) {
213
  $url .= '<strong id="wplnst-results-url-error-title-'.$row->loc_id.'">'.__('Error code ', 'wplnst').$row->curl_errno.'</strong> <span id="wplnst-results-url-error-code-'.$row->loc_id.'" class="wplnst-results-url-error-code"></span><br /><span id="wplnst-results-url-error-desc-'.$row->loc_id.'"></span>';
214
-
215
  // Knowed error
216
  } else {
217
  $url .= '<strong id="wplnst-results-url-error-title-'.$row->loc_id.'">'.esc_html($curl_error['title']).'</strong> <span id="wplnst-results-url-error-code-'.$row->loc_id.'" class="wplnst-results-url-error-code">'.esc_html(sprintf(__('error code %d', 'wplnst'), $row->curl_errno)).'</span><br /><span id="wplnst-results-url-error-desc-'.$row->loc_id.'">'.esc_html($curl_error['desc']).'</span>';
218
  }
 
219
  } else {
220
  $url .= '<strong id="wplnst-results-url-error-title-'.$row->loc_id.'"></strong> <span id="wplnst-results-url-error-code-'.$row->loc_id.'" class="wplnst-results-url-error-code"></span><br /><span id="wplnst-results-url-error-desc-'.$row->loc_id.'"></span>';
221
  }
 
222
  $url .= '</div>';
223
-
224
-
225
  // Check redirection error
226
  $error_redir = !empty($row->redirect_url_id) && empty($row->redirect_url_status) && !empty($row->redirect_curl_errno);
227
  $class_error_redir = $error_redir? '' : 'wplnst-display-none';
228
  $url .= '<div id="wplnst-results-url-error-redir-'.$row->loc_id.'" class="'.$class_error_redir.'">&rarr;&nbsp;';
229
  if ($error_redir) {
230
-
231
  // Retrieve error type
232
  $curl_error = WPLNST_Core_Types_CURL::get_code_info($row->redirect_curl_errno);
233
-
234
  // Unknown
235
  if (empty($curl_error)) {
236
  $url .= '<strong id="wplnst-results-url-error-redir-title-'.$row->loc_id.'">'.__('Error code ', 'wplnst').$row->curl_errno.'</strong> <span id="wplnst-results-url-error-redir-code-'.$row->loc_id.'" class="wplnst-results-url-error-code"></span><br /><span id="wplnst-results-url-error-redir-desc-'.$row->loc_id.'"></span>';
237
-
238
  // Knowed error
239
  } else {
240
  $url .= '<strong id="wplnst-results-url-error-redir-title-'.$row->loc_id.'">'.esc_html($curl_error['title']).'</strong> <span id="wplnst-results-url-error-redir-code-'.$row->loc_id.'" class="wplnst-results-url-error-code">'.esc_html(sprintf(__('error code %d', 'wplnst'), $row->redirect_curl_errno)).'</span><br /><span id="wplnst-results-url-error-redir-desc-'.$row->loc_id.'">'.esc_html($curl_error['desc']).'</span>';
241
  }
 
242
  } else {
243
  $url .= '<strong id="wplnst-results-url-error-redir-title-'.$row->loc_id.'"></strong> <span id="wplnst-results-url-error-redir-code-'.$row->loc_id.'" class="wplnst-results-url-error-code"></span><br /><span id="wplnst-results-url-error-redir-desc-'.$row->loc_id.'"></span>';
244
  }
 
245
  $url .= '</div>';
246
-
247
  // Check relative or absolute
248
  $url .= '<div id="wplnst-results-url-full-'.$row->loc_id.'" class="wplnst-results-url-full'.(($row->relative || $row->absolute)? '' : ' wplnst-display-none').'">'.esc_html($row->url).'</div>';
249
-
250
-
251
  // Prepare data for https mark
252
  $is_https = ('https' == $row->scheme);
253
-
254
  // Prepare data for redirections
255
  $redirs_count = 0;
256
  if ($redirs = ('3' == $row->status_level && $row->redirect_url_id > 0 && !empty($row->redirect_url))) {
257
  $redirs_steps = @json_decode($row->redirect_steps, true);
258
- if (!empty($redirs_steps) && is_array($redirs_steps))
259
  $redirs_count = count($redirs_steps);
 
260
  }
261
-
262
  // Prepare row of marks
263
  $mark_modified = '<span class="wplnst-results-mark wplnst-results-mark-modified' .($row->modified? '' : ' wplnst-display-none').'">'.__('Modified', 'wplnst').'</span>';
264
  $mark_nofollow = '<span class="wplnst-results-mark wplnst-results-mark-nofollow' .($row->nofollow? '' : ' wplnst-display-none').'">nofollow</span>';
@@ -270,35 +277,35 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
270
  $mark_protorel = '<span class="wplnst-results-mark wplnst-results-mark-protorel' .($row->protorel? '' : ' wplnst-display-none').'">'.__('Protocol relative', 'wplnst').'</span>';
271
  $mark_ignored = '<span class="wplnst-results-mark wplnst-results-mark-ignored' .($row->ignored? '' : ' wplnst-display-none').'">'.__('Ignored', 'wplnst').'</span>';
272
  $mark_redirs = '<span class="wplnst-results-mark wplnst-results-mark-redirs' .($redirs? '' : ' wplnst-display-none').'">'.((!$redirs || empty($redirs_count) || 1 == $redirs_count)? '1 redirect' : $redirs_count.' redirects').'</span>';
273
-
274
  // Add new row checking visibility
275
  $mark_visible = ($row->modified || $row->nofollow || $row->relative || $row->absolute || $row->spaced || $row->malformed || $is_https || $row->protorel || $row->ignored || $redirs);
276
  $url .= '<div id="wplnst-results-url-marks-'.$row->loc_id.'" class="wplnst-results-url-marks'.($mark_visible? '' : ' wplnst-display-none').'">'.$mark_modified.$mark_nofollow.$mark_relative.$mark_absolute.$mark_spaced.$mark_malformed.$mark_https.$mark_protorel.$mark_ignored.$mark_redirs.'</div>';
277
-
278
-
279
  // Done
280
  $item['wplnst-url'] = '<div class="wplnst-row-url">'.$url.'</div>';
281
-
282
-
283
-
284
  /* Second column: status, redirection status, and time/size info */
285
-
286
  // Start container
287
  $item['wplnst-status'] = '<div class="wplnst-url-status-code">';
288
-
289
  // Prepare status classes
290
  $class_status_error = empty($row->curl_errno)? ' wplnst-display-none' : '';
291
  $class_status_code = empty($row->status_code)? ' wplnst-display-none' : '';
292
-
293
  // Prepare status Code
294
  $status_code_label = isset($status_codes[$row->status_code])? ' '.$status_codes[$row->status_code] : '';
295
-
296
  // Prepare rechecked mark
297
  $mark_rechecked = ' &nbsp; <span id="wplnst-url-status-recheck-mark-'.$row->loc_id.'" class="wplnst-results-mark wplnst-results-mark-rechecked'.($row->rechecked? '' : ' wplnst-display-none').'">Rechecked</span>';
298
-
299
  // Status code result
300
  $item['wplnst-status'] .= '<div class="wplnst-url-status-code-result"><span id="wplnst-url-status-code-0-loc-'.$row->loc_id.'" class="wplnst-url-status-code-0'.$class_status_error.'">'.__('Request error', 'wplnst').'</span><span id="wplnst-url-status-code-loc-'.$row->loc_id.'" class="wplnst-url-status-code-'.esc_attr($row->status_level).$class_status_code.'">'.esc_html($row->status_code.$status_code_label).'</span>'.$mark_rechecked.'</div>';
301
-
302
  // Prepare redirections status
303
  $redir_status_level = $redir_status_label = '';
304
  $status_redir = (!empty($row->redirect_url_id) && (!empty($row->redirect_url_status) || !empty($row->redirect_curl_errno)));
@@ -306,187 +313,187 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
306
  $redir_status_level = mb_substr($row->redirect_url_status, 0, 1);
307
  $redir_status_label = $row->redirect_url_status.(isset($status_codes[$row->redirect_url_status])? ' '.$status_codes[$row->redirect_url_status] : '');
308
  }
309
-
310
  // Prepare redirection classes
311
  $class_status_redir = $status_redir? '' : ' wplnst-display-none';
312
  $class_status_redir_error = ($status_redir && !empty($row->redirect_curl_errno))? '' : ' wplnst-display-none';
313
  $class_status_redir_code = ($status_redir && !empty($row->redirect_url_status))? '' : ' wplnst-display-none';
314
-
315
  // Redirection status code
316
  $item['wplnst-status'] .= '<div id="wplnst-url-status-code-redir-'.$row->loc_id.'" class="wplnst-url-status-code-redir'.$class_status_redir.'"><span class="wplnst-url-status-code-redir-arrow">&rarr;&nbsp;</span><span id="wplnst-url-status-code-redir-error-'.$row->loc_id.'" class="wplnst-url-status-code-0'.$class_status_redir_error.'">'.__('Request error', 'wplnst').'</span><span id="wplnst-url-status-code-redir-status-'.$row->loc_id.'" class="wplnst-url-status-code-'.esc_attr($redir_status_level).$class_status_redir_code.'">'.esc_html($redir_status_label).'</span></div>';
317
-
318
  // End status container
319
  $item['wplnst-status'] .= '</div>';
320
-
321
  // Time and size
322
  $item['wplnst-status'] .= '<div class="wplnst-url-status-info"><span id="wplnst-url-status-info-time-'.$row->loc_id.'">'.number_format_i18n($row->total_time, 3).' s</span>'.(($row->total_bytes > 0)? '<span id="wplnst-url-status-info-split-'.$row->loc_id.'" class="wplnst-url-status-info-split"> | </span><span id="wplnst-url-status-info-size-'.$row->loc_id.'">'.wplnst_format_bytes($row->total_bytes).'</span>' : '<span id="wplnst-url-status-info-split-'.$row->loc_id.'" class="wplnst-url-status-info-split wplnst-display-none"> | </span><span id="wplnst-url-status-info-size-'.$row->loc_id.'" class="wplnst-display-none"></span>').'</div>';
323
-
324
-
325
-
326
  /* Third column: anchor text */
327
-
328
  // Set text anchor
329
  if ('links' == $row->link_type) {
330
-
331
  // Prepare modified mark
332
  $mark_anchored = '<div id="wplnst-results-anchor-mod-'.$row->loc_id.'" class="wplnst-results-anchor-mod'.($row->anchored? '' : ' wplnst-display-none').'"><span class="wplnst-results-mark wplnst-results-mark-modified">'.__('Modified', 'wplnst').'</span></div>';
333
-
334
  // Anchor text
335
  $item['wplnst-anchor'] = '<div class="wplnst-anchor-link"><span id="wplnst-results-anchor-loc-'.$row->loc_id.'">'.esc_html($row->anchor).'</span>'.$mark_anchored.'</div>';
336
-
337
  // Is an image
338
  } elseif ('images' == $row->link_type) {
339
 
340
  // Image info
341
  $item['wplnst-anchor'] = '<div class="wplnst-anchor-image wplnst-row-dashicon"><span>'.esc_html(__('Image', 'wplnst')).'</span></div>';
342
  }
343
-
344
-
345
-
346
  /* Fourth column: Content host */
347
-
348
  // Check no isolated
349
  if (!$this->results->isolated) {
350
-
351
  // Default content link
352
  $item['wplnst-content'] = $row->object_type.' '.$row->object_id;
353
-
354
  // Extract identifier
355
  $object_id = (int) $row->object_id;
356
-
357
  // Column content for posts
358
  if ('posts' == $row->object_type) {
359
-
360
- // Retrieve post
361
  $post = get_post($object_id);
362
-
363
  // Check post object
364
  if (!empty($post) && is_object($post) && 'WP_Post' == get_class($post)) {
365
-
366
  // Copy object
367
  $item['post'] = $post;
368
  $item['can_edit'] = current_user_can('edit_post', $post->ID);
369
-
370
  // Prepare title
371
  $title = _draft_or_post_title($post);
372
-
373
  // Check edit post link
374
  if ($item['can_edit'] && 'trash' != $post->post_status) {
375
-
376
  // Copy edit post link
377
  $item['edit_post_link'] = get_edit_post_link($post->ID);
378
-
379
  // Editable post link
380
  $post_row = '<strong><a href="'.$item['edit_post_link'].'" title="'.esc_attr(sprintf(__( 'Edit &#8220;%s&#8221;'), $title)).'" target="_blank">'.$title.'</a></strong>';
381
-
382
  // Post without link
383
  } else {
384
-
385
  // Only title
386
  $post_row = '<strong>'.$title.'</strong>';
387
  }
388
-
389
  // Not found
390
  } else {
391
-
392
  // Not found item
393
  $post_row = sprintf(__('Entry %d not found', 'wplnst'), $object_id);
394
  }
395
-
396
  // Set column value
397
  $item['wplnst-content'] = '<div class="wplnst-content-post wplnst-row-dashicon"><span>'.$post_row.'</span></div>';
398
-
399
  // Column content for comments
400
  } elseif ('comments' == $row->object_type) {
401
-
402
  // Retrieve comment
403
  $object_id = (int) $row->object_id;
404
  $comment = get_comment($object_id);
405
-
406
  // Check comment object
407
  if (!empty($comment) && is_object($comment)) {
408
-
409
  // Copy object
410
  $item['comment'] = $comment;
411
  $item['can_edit'] = current_user_can('edit_comment', $comment->comment_ID);
412
-
413
  // Isolate comment author
414
  $comment_author = ('' === $comment->comment_author)? '' : '<strong>'.esc_html($comment->comment_author).'</strong> &#8212; ';
415
-
416
  // First comment chars
417
  $comment_text = wplnst_crop_text($comment->comment_content, 50);
418
-
419
  // Check editable comment
420
  if ($item['can_edit']) {
421
-
422
  // Submitted on link
423
  $comment_row = '<a href="'.admin_url('comment.php?action=editcomment&c='.$comment->comment_ID).'">'.$comment_author.$comment_text.'</a>';
424
-
425
  // Check approved comment
426
  } elseif ('approved' == wp_get_comment_status($comment->comment_ID)) {
427
-
428
  // View comment
429
  $comment_row = '<a href="'.esc_url(get_comment_link($comment->comment_ID)).'" target="_blank">'.$comment_author.$comment_text.'</a>';
430
-
431
  // No link
432
  } else {
433
-
434
  // Only text
435
  $comment_row = $comment_author.$comment_text;
436
  }
437
-
438
  // Not found
439
  } else {
440
-
441
  // Not found item
442
  $comment_row = sprintf(__('Comment %d not found', 'wplnst'), $object_id);
443
  }
444
-
445
  // Set column value
446
  $item['wplnst-content'] = '<div class="wplnst-content-comment wplnst-row-dashicon"><span>'.$comment_row.'</span></div>';
447
-
448
  // Column content for links
449
  } elseif ('blogroll' == $row->object_type) {
450
-
451
  // Retrieve link
452
  $object_id = (int) $row->object_id;
453
  $bookmark = get_bookmark($object_id);
454
-
455
  // Check link object
456
  if (!empty($bookmark) && is_object($bookmark)) {
457
-
458
  // Copy object
459
  $item['bookmark'] = $bookmark;
460
  $item['can_edit'] = current_user_can('manage_links', $bookmark->link_id);
461
-
462
  // Prepare visible URL
463
  $link_url = esc_html(url_shorten($bookmark->link_url));
464
-
465
  // Check editable comment
466
  if ($item['can_edit']) {
467
-
468
  // Submitted on link
469
  $bookmark_row = '<a href="'.admin_url('link.php?action=edit&link_id='.((int) $bookmark->link_id)).'" target="_blank">'.$link_url.'</a>';
470
-
471
  // No link
472
  } else {
473
-
474
  // Only text
475
  $bookmark_row = '<a href="'.esc_url($link->link_url).'" target="_blank" target="_blank">'.$link_url.'</a>';
476
  }
477
-
478
  // Not found
479
  } else {
480
-
481
  // Not found item
482
  $bookmark_row = sprintf(__('Bookmark %d not found', 'wplnst'), $object_id);
483
  }
484
-
485
  // Set column value
486
  $item['wplnst-content'] = '<div class="wplnst-content-bookmark wplnst-row-dashicon"><span>'.$bookmark_row.'</span></div>';
487
  }
488
  }
489
-
490
  // Add row
491
  $this->items[] = $item;
492
  }
@@ -532,64 +539,70 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
532
  * @return mixed
533
  */
534
  protected function column_default($item, $column_name) {
535
-
536
  // Actions for URL column
537
  if ('wplnst-url' == $column_name) {
538
-
539
  // URL actions row
540
  $actions = $this->column_actions_url($item);
541
- if (!empty($actions) && is_array($actions))
542
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
543
-
 
544
  // Actions for status column
545
  } elseif ('wplnst-status' == $column_name) {
546
-
547
  // Status actions row
548
  $actions = $this->column_actions_status($item);
549
- if (!empty($actions) && is_array($actions))
550
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
551
-
 
552
  // Actions for the link anchor
553
  } elseif ('wplnst-anchor' == $column_name) {
554
-
555
  // Check links type and available anchor
556
  if ('links' == $item['link_type'] && false === strpos($item['object_field'], 'custom_field_url_')) {
557
-
558
  // Anchor actions row
559
  $actions = $this->column_actions_anchor($item);
560
- if (!empty($actions) && is_array($actions))
561
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
 
562
  }
563
-
564
  // Actions for content column
565
  } elseif ('wplnst-content' == $column_name) {
566
-
567
  // Posts actions
568
  if ('posts' == $item['object_type']) {
569
-
570
  // Content post actions row
571
  $actions = $this->column_actions_content_posts($item);
572
- if (!empty($actions) && is_array($actions))
573
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
574
-
 
575
  // Comments actions
576
  } elseif ('comments' == $item['object_type']) {
577
-
578
  // Content comments actions row
579
  $actions = $this->column_actions_content_comments($item);
580
- if (!empty($actions) && is_array($actions))
581
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
582
-
 
583
  // Blogroll actions
584
  } elseif ('blogroll' == $item['object_type']) {
585
-
586
  // Content bookmarks actions row
587
  $actions = $this->column_actions_content_blogroll($item);
588
- if (!empty($actions) && is_array($actions))
589
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
 
590
  }
591
  }
592
-
593
  // Default column
594
  return $item[$column_name];
595
  }
@@ -600,24 +613,24 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
600
  * Column URL row actions
601
  */
602
  private function column_actions_url($item) {
603
-
604
  // Initialize
605
  $actions = array();
606
-
607
  // For not isolated
608
  if (!$this->results->isolated) {
609
-
610
  // Check object
611
  if (isset($item['can_edit']) && $item['can_edit']) {
612
-
613
  // Add results actions
614
- $actions = apply_filters('wplnst_results_actions_url', $actions, $item);
615
  }
616
-
617
  // Filter by URL (for future versions)
618
  // $actions['wplnst-action-filter'] = '<a href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_locations($this->results->scan->id, $item['url_id'])).'" class="wplnst-results-action">'.__('Filter by URL', 'wplnst').'</a>';
619
  }
620
-
621
  // Done
622
  return $actions;
623
  }
@@ -628,17 +641,17 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
628
  * Column Status row actions
629
  */
630
  private function column_actions_status($item) {
631
-
632
  // Initialize
633
  $actions = array();
634
-
635
  // For not isolated
636
  if (!$this->results->isolated) {
637
-
638
  // Add results actions
639
  $actions = apply_filters('wplnst_results_actions_status', $actions, $item);
640
  }
641
-
642
  // Done
643
  return $actions;
644
  }
@@ -649,21 +662,21 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
649
  * Column Anchor row actions
650
  */
651
  private function column_actions_anchor($item) {
652
-
653
  // Initialize
654
  $actions = array();
655
-
656
  // For not isolated
657
  if (!$this->results->isolated) {
658
-
659
  // Check editable object
660
  if (isset($item['can_edit']) && $item['can_edit']) {
661
-
662
  // Add results actions
663
  $actions = apply_filters('wplnst_results_actions_anchor', $actions, $item);
664
  }
665
  }
666
-
667
  // Done
668
  return $actions;
669
  }
@@ -674,45 +687,48 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
674
  * Column content row actions for posts
675
  */
676
  private function column_actions_content_posts($item) {
677
-
678
  // Check object
679
  if (!isset($item['post']))
680
  return array();
681
-
682
  // Initialize
683
  $actions = array();
684
  $post = $item['post'];
685
-
686
  // Permissions
687
  $can_edit_post = $item['can_edit'];
688
  $post_type_object = get_post_type_object($post->post_type);
689
-
690
  // Check edit post action
691
- if ($can_edit_post && 'trash' != $post->post_status)
692
  $actions['edit'] = '<a href="'.$item['edit_post_link'].'" title="'.esc_attr__('Edit this item').'" target="_blank">'.__( 'Edit' ).'</a>';
693
-
 
694
  // Check delete post action
695
  if (current_user_can('delete_post', $post->ID)) {
696
-
697
  // Post in trash
698
- if ('trash' == $post->post_status)
699
  $actions['untrash'] = "<a title='" . esc_attr__( 'Restore this item from the Trash' ) . "' href='" . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore' ) . "</a>";
700
-
701
  // Post to trash
702
- elseif (EMPTY_TRASH_DAYS)
703
  $actions['trash'] = "<a class='submitdelete' title='".esc_attr__('Move this item to the Trash')."' href='".get_delete_post_link($post->ID)."'>".__('Trash')."</a>";
704
-
 
705
  // Remove Permanently
706
- if ('trash' == $post->post_status || !EMPTY_TRASH_DAYS)
707
  $actions['delete'] = "<a class='submitdelete wplnst-remove-entry' title='".esc_attr__('Delete this item permanently')."' href='".get_delete_post_link($post->ID, '', true)."'>".__('Delete Permanently')."</a>";
 
708
  }
709
-
710
  // Check view post action
711
  if ($post_type_object->public) {
712
-
713
  // Post title
714
  $title = _draft_or_post_title();
715
-
716
  // Not published
717
  if (in_array($post->post_status, array('pending', 'draft', 'future'))) {
718
  if ($can_edit_post) {
@@ -721,13 +737,13 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
721
  $preview_link = apply_filters( 'preview_post_link', add_query_arg('preview', 'true', $preview_link ), $post );
722
  $actions['view'] = '<a href="' . esc_url( $preview_link ) . '" title="' . esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;' ), $title ) ) . '" rel="permalink" target="_blank">' . __( 'Preview' ) . '</a>';
723
  }
724
-
725
  // Not in trash
726
  } elseif ( 'trash' != $post->post_status ) {
727
  $actions['view'] = '<a href="' . get_permalink( $post->ID ) . '" title="' . esc_attr( sprintf( __( 'View &#8220;%s&#8221;' ), $title ) ) . '" rel="permalink" target="_blank">' . __( 'View' ) . '</a>';
728
  }
729
  }
730
-
731
  // Done
732
  return $actions;
733
  }
@@ -738,28 +754,28 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
738
  * Column content row actions for comments
739
  */
740
  private function column_actions_content_comments($item) {
741
-
742
  // Check object
743
  if (!isset($item['comment']))
744
  return array();
745
-
746
  // Initialize
747
  $actions = array();
748
  $comment = $item['comment'];
749
-
750
  // Check editable comment
751
  if ($item['can_edit']) {
752
-
753
  // Real comment status
754
  $the_comment_status = wp_get_comment_status($comment->comment_ID);
755
-
756
  // Remove and approve nonces
757
  $del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) );
758
  $approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) );
759
-
760
  // Base URL
761
  $url = "comment.php?c=$comment->comment_ID";
762
-
763
  // All URLs
764
  $approve_url = esc_url( $url . "&action=approvecomment&$approve_nonce" );
765
  $unapprove_url = esc_url( $url . "&action=unapprovecomment&$approve_nonce" );
@@ -768,7 +784,7 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
768
  $trash_url = esc_url( $url . "&action=trashcomment&$del_nonce" );
769
  $untrash_url = esc_url( $url . "&action=untrashcomment&$del_nonce" );
770
  $delete_url = esc_url( $url . "&action=deletecomment&$del_nonce" );
771
-
772
  // Preorder it: Edit | Approve | Spam | Trash.
773
  $actions = array(
774
  'edit' => '',
@@ -782,34 +798,36 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
782
  } elseif ( 'unapproved' == $the_comment_status ) {
783
  $actions['approvecomment'] = "<a href='$approve_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID:e7e7d3:action=dim-comment&amp;new=approved' class='vim-a vim-destructive' title='" . esc_attr__( 'Approve this comment' ) . "'>" . __( 'Approve' ) . '</a>';
784
  }
785
-
786
  if ( 'spam' != $the_comment_status ) {
787
  $actions['spam'] = "<a href='$spam_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::spam=1' class='vim-s vim-destructive' title='" . esc_attr__( 'Mark this comment as spam' ) . "'>" . /* translators: mark as spam link */ _x( 'Spam', 'verb' ) . '</a>';
788
  } elseif ( 'spam' == $the_comment_status ) {
789
  $actions['unspam'] = "<a href='$unspam_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID:66cc66:unspam=1' class='vim-z vim-destructive'>" . _x( 'Not Spam', 'comment' ) . '</a>';
790
  }
791
-
792
  if ( 'trash' == $the_comment_status ) {
793
  $actions['untrash'] = "<a href='$untrash_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID:66cc66:untrash=1' class='vim-z vim-destructive'>" . __( 'Restore' ) . '</a>';
794
  }
795
-
796
  if ( 'spam' == $the_comment_status || 'trash' == $the_comment_status || !EMPTY_TRASH_DAYS ) {
797
  $actions['delete'] = "<a href='$delete_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::delete=1' class='delete vim-d vim-destructive wplnst-remove-comment'>" . __( 'Delete Permanently' ) . '</a>';
798
  } else {
799
  $actions['trash'] = "<a href='$trash_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::trash=1' class='delete vim-d vim-destructive' title='" . esc_attr__( 'Move this comment to the trash' ) . "'>" . _x( 'Trash', 'verb' ) . '</a>';
800
  }
801
-
802
- if ('spam' != $the_comment_status && 'trash' != $the_comment_status)
803
  $actions['edit'] = "<a href='comment.php?action=editcomment&amp;c={$comment->comment_ID}' title='" . esc_attr__( 'Edit comment' ) . "'>". __( 'Edit' ) . '</a>';
 
804
  }
805
-
806
  // Check approved comment to see it
807
- if ('approved' == wp_get_comment_status($comment->comment_ID))
808
  $actions['view'] = '<a href="'.esc_url(get_comment_link($comment->comment_ID)).'" target="_blank">'.__('View').'</a>';
809
-
 
810
  /** This filter is documented in wp-admin/includes/dashboard.php */
811
  $actions = apply_filters('comment_row_actions', array_filter($actions), $comment);
812
-
813
  // Done
814
  return $actions;
815
  }
@@ -820,29 +838,30 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
820
  * Column content row actions for blogroll
821
  */
822
  private function column_actions_content_blogroll($item) {
823
-
824
  // Check object
825
- if (!isset($item['bookmark']))
826
  return array();
827
-
 
828
  // Initialize
829
  $actions = array();
830
  $bookmark = $item['bookmark'];
831
-
832
  // Check editable comment
833
  if ($item['can_edit']) {
834
-
835
  // Cast identifier
836
  $bookmark_id = (int) $bookmark->link_id;
837
-
838
  // Edit or remove link
839
  $actions['edit'] = '<a href="'.admin_url('link.php?action=edit&link_id='.$bookmark_id).'" target="_blank">'.__('Edit').'</a>';
840
  $actions['trash'] = '<a class="wplnst-remove-bookmark" href="'.wp_nonce_url('link.php?action=delete&link_id='.$bookmark_id, 'delete-bookmark_'.$bookmark_id).'" target="_blank">'.__('Delete').'</a>';
841
  }
842
-
843
  // Visit action
844
  $actions['visit'] = '<a href="'.esc_url($bookmark->link_url).'" target="_blank">'.__('Visit', 'wplnst').'</a>';
845
-
846
  // Done
847
  return $actions;
848
  }
@@ -860,13 +879,14 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
860
  * @return string
861
  */
862
  protected function row_actions( $actions, $loc_id = 0 ) {
863
-
864
  $action_count = count( $actions );
865
  $i = 0;
866
-
867
- if ( !$action_count )
868
  return '';
869
-
 
870
  $out = '<div class="row-actions wplnst-row-actions wplnst-row-actions-'.$loc_id.'">';
871
  foreach ( $actions as $action => $link ) {
872
  ++$i;
@@ -874,7 +894,7 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
874
  $out .= "<span class='$action'>$link$sep</span>";
875
  }
876
  $out .= '</div>';
877
-
878
  return $out;
879
  }
880
 
@@ -905,31 +925,33 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
905
  * @access public
906
  */
907
  public function display() {
908
-
909
  // Wrapper form
910
  echo '<form method="get" action="'.esc_url(remove_query_arg('paged', set_url_scheme('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']))).'" id="wplnst-results" data-nonce="'.esc_attr(wp_create_nonce('wplnst-results-'.$this->results->scan->hash)).'" data-nonce-advanced-display="'.esc_attr(wp_create_nonce('wplnst-results-advanced-display')).'" data-confirm-delete-entry="'.esc_attr__('Please, confirm you want to remove this entry pressing the Ok button', 'wplnst').'" data-confirm-delete-comment="'.esc_attr__('Please, confirm you want to remove this comment pressing the Ok button', 'wplnst').'" data-confirm-delete-bookmark="'.esc_attr__('Please, confirm you want to remove this bookmark pressing the Ok button', 'wplnst').'" data-label-action-url-redir="'.esc_attr__('Apply Redirection', 'wplnst').'" data-label-server-comm-error="'.esc_attr(WPLNST_Core_Text::get_text('server_comm_error')).'" data-label-unknown-error="'.esc_attr(WPLNST_Core_Text::get_text('unknown_error')).'" data-label-select-any="'.esc_attr__('Please, select any result to proceed', 'wplnst').'" data-label-error-code="'.esc_attr__('error code', 'wplnst').'">';
911
-
912
  // Hidden fields
913
  echo '<input type="hidden" name="page" value="'.esc_attr($_GET['page']).'" />';
914
  echo '<input type="hidden" name="scan_id" value="'.esc_attr($this->results->scan->id).'" />';
915
  echo '<input type="hidden" name="context" value="results" />';
916
  if (isset($this->results->status_level)) echo '<input type="hidden" name="status" value="'.esc_attr($this->results->status_level).'" />';
917
-
918
  // Raise event at this point
919
  do_action('wplnst_scans_results_view_display');
920
-
921
  // Check isolated classes
922
  $extra_classes = array();
923
- if ($this->results->isolated)
924
  $extra_classes[] = 'wplnst-isolated-table';
925
-
 
926
  // Show levels menu
927
  $this->menu();
928
-
929
  // Check isolated display
930
- if (!$this->results->isolated)
931
  $this->display_tablenav('top');
932
-
 
933
  ?><table class="wp-list-table <?php echo implode(' ', array_merge($this->get_table_classes(), $extra_classes)); ?>">
934
  <thead>
935
  <tr>
@@ -947,11 +969,12 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
947
  </tfoot>
948
  <?php endif; ?>
949
  </table><?php
950
-
951
  // Check isolated display
952
- if (!$this->results->isolated)
953
  $this->display_tablenav('bottom');
954
-
 
955
  // Close form
956
  echo '</form>';
957
  }
@@ -980,14 +1003,14 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
980
  * Display a menu based on status levels
981
  */
982
  private function menu() {
983
-
984
  // Initialize
985
  $status_levels = WPLNST_Core_Types::get_status_levels();
986
-
987
  // Enum summary elements
988
  $levels = array();
989
  foreach ($this->results->scan->summary as $key => $value) {
990
-
991
  // Status level record
992
  if (0 === strpos($key, 'status_level_')) {
993
  $key = explode('status_level_', $key);
@@ -1001,31 +1024,34 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
1001
  }
1002
  }
1003
  }
1004
-
1005
  // Status levels menu
1006
  $menu_levels = array();
1007
  foreach ($status_levels as $key => $label) {
1008
- if (in_array($key, array_keys($levels)))
1009
  $menu_levels[$key] = $levels[$key];
 
1010
  }
1011
-
1012
  // Check stored total
1013
  $total = empty($this->results->scan->summary['status_total'])? 0 : (int) $this->results->scan->summary['status_total'];
1014
-
1015
  // Menu levels
1016
  $menu_links = array();
1017
-
1018
  // All results
1019
  $menu_links[] = '<a href="'.$this->base_url.'"'.($total > 0 && $this->results->is_all_results? ' class="current"' : '').'>'.__('All results', 'wplnst').' </a><span class="count">('.($this->results->is_all_results? number_format_i18n($this->results->total_rows) : number_format_i18n($total)).')</span>';
1020
-
1021
  // Request error
1022
- if (!empty($levels['0']))
1023
  $menu_links[] = '<a href="'.$this->base_url.'&status=0"'.(('0' === $this->results->status_level && !$this->results->is_search)? ' class="current"' : '').'>'.__('Request error', 'wplnst').' </a><span class="count">('.number_format_i18n($levels['0']).')</span>';
1024
-
 
1025
  // Level results
1026
- foreach ($menu_levels as $key => $total)
1027
  $menu_links[] = '<a href="'.$this->base_url.'&status='.$key.'"'.(($key == $this->results->status_level && !$this->results->is_search)? ' class="current"' : '').'>'.esc_html($key.'00s '.$status_levels[$key]).' </a><span class="count">('.number_format_i18n($total).')</span>';
1028
-
 
1029
  // Show menu
1030
  echo '<div id="wplnst-levels-menu" class="wplnst-clearfix'.($this->results->isolated? ' wplnst-levels-menu-isolated' : '').'"><ul class="subsubsub"><li>'.implode(' | </li><li>', $menu_links).'</li></ul>'.(('end' != $this->results->scan->status)? '<div class="alignright wplnst-aproximate-total">'.__('(counters in progress)', 'wplnst').'</div>' : '').'</div>';
1031
  }
@@ -1036,19 +1062,21 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
1036
  * Display a set of filters
1037
  */
1038
  protected function filters() {
1039
-
1040
  // Check filters
1041
  $fields = $this->filters_fields();
1042
- if (empty($fields))
1043
  return;
1044
-
 
1045
  // Show menu, actions, etc.
1046
  echo '<div id="wplnst-results-filters" class="alignleft actions'.$this->filters_classes().'">';
1047
-
1048
  // Display fields
1049
- foreach ($fields as $key => $field)
1050
  echo '<select id="wplnst-filter-'.$key.'"><option value="">'.esc_html($field['title']).'</option>'.$field['options'].'</select>';
1051
-
 
1052
  // Button and end of div
1053
  echo '&nbsp;<input id="wplnst-filter-button" data-fields="'.implode(',', array_keys($fields)).'" data-href="'.esc_attr($this->base_url).'" class="button" type="button" value="'.__('Filter', 'wplnst').'" /></div>';
1054
  }
@@ -1068,22 +1096,22 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
1068
  * Retrieve fields for basic filters
1069
  */
1070
  protected function filters_fields() {
1071
-
1072
  // Basic fields
1073
  $fields = array();
1074
-
1075
-
1076
  /* Status codes filter */
1077
-
1078
  // Initialize
1079
  $objects_types = WPLNST_Core_Types::get_objects_types();
1080
  $status_levels = WPLNST_Core_Types::get_status_levels();
1081
  $status_codes_raw = WPLNST_Core_Types::get_status_codes_raw();
1082
-
1083
  // Enum summary elements
1084
  $levels = $codes = $objects = array();
1085
  foreach ($this->results->scan->summary as $key => $value) {
1086
-
1087
  // Status codes
1088
  if (0 === strpos($key, 'status_code_')) {
1089
  $key = explode('status_code_', $key);
@@ -1093,23 +1121,25 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
1093
  $levels['0'] = true;
1094
  } elseif (3 == strlen($key) && isset($status_codes_raw[$key])) {
1095
  $level = substr($key, 0, 1);
1096
- if (isset($status_levels[$level]))
1097
  $levels[$level] = isset($levels[$level])? $levels[$level] + 1 : 1;
 
1098
  $codes[$key] = $value;
1099
  }
1100
  }
1101
-
1102
  // Objects match
1103
  } elseif (0 === strpos($key, 'objects_match_')) {
1104
  $key = explode('objects_match_', $key);
1105
- if (2 == count($key) && in_array($key[1], array_keys($objects_types)))
1106
  $objects[$key[1]] = $value;
 
1107
  }
1108
  }
1109
-
1110
-
1111
  /* Status codes options */
1112
-
1113
  // Collect options
1114
  $options_codes = empty($levels['0'])? '' : '<option '.((isset($this->results->status_level) && '0' === $this->results->status_level)? 'selected' : '').' value="0">'.__('Request error', 'wplnst').'</option>';
1115
  $options_levels = array();
@@ -1123,60 +1153,63 @@ class WPLNST_Views_Scans_Results extends WP_List_Table {
1123
  $options_codes .= '<option '.((!empty($this->results->status_code) && $this->results->status_code == $key)? 'selected' : '').' value="'.$key.'">'.$key.' '.$label.'</option>';
1124
  }
1125
  }
1126
-
1127
  // Add filter
1128
  $fields['status'] = array(
1129
  'type' => 'select',
1130
  'title' => __('All status codes', 'wplnst'),
1131
  'options' => $options_codes,
1132
  );
1133
-
1134
-
1135
  /* Objects options */
1136
-
1137
  // Collect custom post types
1138
  $options_post_types = '';
1139
  if (in_array('posts', array_keys($objects))) {
1140
  $post_types = WPLNST_Core_Types::get_post_types();
1141
  foreach ($post_types as $type => $name) {
1142
- if (in_array($type, $this->results->scan->post_types))
1143
  $options_post_types .= '<option '.((!empty($this->results->object_post_type) && $this->results->object_post_type == $type)? 'selected' : '').' value="posts_'.$type.'">&mdash;'.esc_html($name).'</option>';
 
1144
  }
1145
  }
1146
-
1147
  // Collect options
1148
  $objects_codes = '';
1149
  foreach ($objects_types as $key => $value) {
1150
  if (in_array($key, array_keys($objects))) {
1151
  $objects_codes .= '<option '.((!empty($this->results->object_type) && $this->results->object_type == $key)? 'selected' : '').' value="'.$key.'">'.$value.'</option>';
1152
- if ('posts' == $key)
1153
  $objects_codes .= $options_post_types;
 
1154
  }
1155
  }
1156
-
1157
  // Check filter
1158
  $fields['otype'] = array(
1159
  'type' => 'select',
1160
  'title' => __('All content', 'wplnst'),
1161
  'options' => $objects_codes,
1162
  );
1163
-
1164
-
1165
  /* Options for link types */
1166
-
1167
  $options_ltypes = '';
1168
  $link_types = WPLNST_Core_Types::get_link_types();
1169
- foreach ($link_types as $link_type => $link_type_name)
1170
  $options_ltypes .= '<option '.((!empty($this->results->link_type) && $this->results->link_type == $link_type)? 'selected' : '').' value="'.esc_attr($link_type).'">'.esc_html($link_type_name).'</option>';
1171
-
 
1172
  // Check filter
1173
  $fields['ltype'] = array(
1174
  'type' => 'select',
1175
  'title' => __('All link types', 'wplnst'),
1176
  'options' => $options_ltypes,
1177
  );
1178
-
1179
-
1180
  // Done
1181
  return $fields;
1182
  }
1
  <?php
2
 
3
  // Check WP constant
4
+ if (!defined('ABSPATH')) {
5
  die;
6
+ }
7
 
8
  // Check dependencies
9
+ if (!class_exists('WP_List_Table')) {
10
+ require_once ABSPATH.'wp-admin/includes/class-wp-list-table.php';
11
+ }
12
 
13
  /**
14
+ * Scans Results class
15
  *
16
  * @package WP Link Status
17
+ * @subpackage Views
18
  */
19
  class WPLNST_Views_Scans_Results extends WP_List_Table {
20
 
48
  * Constructor
49
  */
50
  public function __construct($results) {
51
+
52
  // Dependencies
53
  wplnst_require('core', 'util-math');
54
  wplnst_require('core', 'util-string');
55
+
56
  // Parent constructor
57
  parent::__construct();
58
+
59
  // Copy results
60
  $this->results = $results;
61
+
62
  // Base link for filters
63
  $this->base_url = esc_url(WPLNST_Core_Plugin::get_url_scans_results($this->results->scan->id));
64
  }
74
  * Prepare columns and data
75
  */
76
  function prepare_items() {
77
+
78
  // Columns
79
  $this->setup_columns();
80
+
81
  // Data items
82
  $this->setup_items();
83
+
84
  // Pagination
85
  $this->setup_pagination();
86
  }
91
  * Setup columns
92
  */
93
  private function setup_columns() {
94
+
95
  // Initialize
96
  $hidden = array();
97
  $sortable = array();
98
+
99
  // Column headers
100
  $this->_column_headers = array($this->get_columns(), $hidden, $sortable);
101
  }
106
  * Columns array
107
  */
108
  public function get_columns(){
109
+
110
  // Prepare
111
  $columns = array(
112
  'cb' => '<input type="checkbox" />',
115
  'wplnst-anchor' => __('Anchor text', 'wplnst'),
116
  'wplnst-content' => __('Content', 'wplnst'),
117
  );
118
+
119
  // Exception
120
  if ($this->results->isolated) {
121
  unset($columns['cb']);
123
  } elseif (!$this->get_columns_cb()) {
124
  unset($columns['cb']);
125
  }
126
+
127
  // Done
128
  return $columns;
129
  }
143
  * Setup data items
144
  */
145
  private function setup_items() {
146
+
147
  // Dependencies
148
  wplnst_require('core', 'types-curl');
149
+
150
  // Initialize
151
  $status_levels = WPLNST_Core_Types::get_status_levels();
152
  $status_codes = WPLNST_Core_Types::get_status_codes_raw();
153
+
154
  // Populate data
155
  $this->items = array();
156
  foreach ($this->results->rows as $row) {
157
+
158
+
159
  // Normalize identifier
160
  $item = array(
161
  'ID' => $row->url_id,
175
  'anchored' => $row->anchored,
176
  'attributed' => $row->attributed,
177
  );
178
+
179
+
180
  /* First column: URL */
181
+
182
+
183
  // Add unlinked flag
184
  $url = '<span id="wplnst-results-url-unlinked-'.$row->loc_id.'" class="wplnst-results-mark wplnst-results-mark-unlinked'.($row->unlinked? '' : ' wplnst-display-none').'">'.__('Unlinked', 'wplnst').'</span>';
185
+
186
  // Check link
187
  if ('http' == $row->scheme || 'https' == $row->scheme || 'ftp' == $row->scheme) {
188
+
189
  // Link to an browser resource
190
  $url .= '<strong><a href="'.esc_url($row->url).'" target="_blank" id="wplnst-results-url-loc-'.$row->loc_id.'" title="'.esc_url($row->url).'">'.esc_html($row->raw_url).'</a></strong>';
191
+
192
  // No link
193
  } else {
194
+
195
  // Unsupported linkable protocol
196
  $url .= '<strong><span id="wplnst-results-url-loc-'.$row->loc_id.'">'.esc_html($row->raw_url).'</span></strong>';
197
  }
198
+
199
+
200
  // Redirection
201
  $class_redirection = ('3' == $row->status_level && $row->redirect_url_id > 0 && !empty($row->redirect_url))? '' : 'wplnst-display-none';
202
  $url .= '<span id="wplnst-results-url-redir-'.$row->loc_id.'" class="'.$class_redirection.'"><br />&rarr;&nbsp;<a id="wplnst-results-url-redir-href-'.$row->loc_id.'" href="'.esc_url($row->redirect_url).'" target="_blank">'.esc_html($row->redirect_url).'</a></span>';
203
+
204
+
205
  // Check error
206
  $class_error = (!empty($row->status_code) || empty($row->curl_errno))? 'wplnst-display-none' : '';
207
  $url .= '<div id="wplnst-results-url-error-'.$row->loc_id.'" class="'.$class_error.'">';
208
  if (empty($row->status_code) && !empty($row->curl_errno)) {
209
+
210
  // Retrieve error type
211
  $curl_error = WPLNST_Core_Types_CURL::get_code_info($row->curl_errno);
212
+
213
  // Unknown
214
  if (empty($curl_error)) {
215
  $url .= '<strong id="wplnst-results-url-error-title-'.$row->loc_id.'">'.__('Error code ', 'wplnst').$row->curl_errno.'</strong> <span id="wplnst-results-url-error-code-'.$row->loc_id.'" class="wplnst-results-url-error-code"></span><br /><span id="wplnst-results-url-error-desc-'.$row->loc_id.'"></span>';
216
+
217
  // Knowed error
218
  } else {
219
  $url .= '<strong id="wplnst-results-url-error-title-'.$row->loc_id.'">'.esc_html($curl_error['title']).'</strong> <span id="wplnst-results-url-error-code-'.$row->loc_id.'" class="wplnst-results-url-error-code">'.esc_html(sprintf(__('error code %d', 'wplnst'), $row->curl_errno)).'</span><br /><span id="wplnst-results-url-error-desc-'.$row->loc_id.'">'.esc_html($curl_error['desc']).'</span>';
220
  }
221
+
222
  } else {
223
  $url .= '<strong id="wplnst-results-url-error-title-'.$row->loc_id.'"></strong> <span id="wplnst-results-url-error-code-'.$row->loc_id.'" class="wplnst-results-url-error-code"></span><br /><span id="wplnst-results-url-error-desc-'.$row->loc_id.'"></span>';
224
  }
225
+
226
  $url .= '</div>';
227
+
228
+
229
  // Check redirection error
230
  $error_redir = !empty($row->redirect_url_id) && empty($row->redirect_url_status) && !empty($row->redirect_curl_errno);
231
  $class_error_redir = $error_redir? '' : 'wplnst-display-none';
232
  $url .= '<div id="wplnst-results-url-error-redir-'.$row->loc_id.'" class="'.$class_error_redir.'">&rarr;&nbsp;';
233
  if ($error_redir) {
234
+
235
  // Retrieve error type
236
  $curl_error = WPLNST_Core_Types_CURL::get_code_info($row->redirect_curl_errno);
237
+
238
  // Unknown
239
  if (empty($curl_error)) {
240
  $url .= '<strong id="wplnst-results-url-error-redir-title-'.$row->loc_id.'">'.__('Error code ', 'wplnst').$row->curl_errno.'</strong> <span id="wplnst-results-url-error-redir-code-'.$row->loc_id.'" class="wplnst-results-url-error-code"></span><br /><span id="wplnst-results-url-error-redir-desc-'.$row->loc_id.'"></span>';
241
+
242
  // Knowed error
243
  } else {
244
  $url .= '<strong id="wplnst-results-url-error-redir-title-'.$row->loc_id.'">'.esc_html($curl_error['title']).'</strong> <span id="wplnst-results-url-error-redir-code-'.$row->loc_id.'" class="wplnst-results-url-error-code">'.esc_html(sprintf(__('error code %d', 'wplnst'), $row->redirect_curl_errno)).'</span><br /><span id="wplnst-results-url-error-redir-desc-'.$row->loc_id.'">'.esc_html($curl_error['desc']).'</span>';
245
  }
246
+
247
  } else {
248
  $url .= '<strong id="wplnst-results-url-error-redir-title-'.$row->loc_id.'"></strong> <span id="wplnst-results-url-error-redir-code-'.$row->loc_id.'" class="wplnst-results-url-error-code"></span><br /><span id="wplnst-results-url-error-redir-desc-'.$row->loc_id.'"></span>';
249
  }
250
+
251
  $url .= '</div>';
252
+
253
  // Check relative or absolute
254
  $url .= '<div id="wplnst-results-url-full-'.$row->loc_id.'" class="wplnst-results-url-full'.(($row->relative || $row->absolute)? '' : ' wplnst-display-none').'">'.esc_html($row->url).'</div>';
255
+
256
+
257
  // Prepare data for https mark
258
  $is_https = ('https' == $row->scheme);
259
+
260
  // Prepare data for redirections
261
  $redirs_count = 0;
262
  if ($redirs = ('3' == $row->status_level && $row->redirect_url_id > 0 && !empty($row->redirect_url))) {
263
  $redirs_steps = @json_decode($row->redirect_steps, true);
264
+ if (!empty($redirs_steps) && is_array($redirs_steps)) {
265
  $redirs_count = count($redirs_steps);
266
+ }
267
  }
268
+
269
  // Prepare row of marks
270
  $mark_modified = '<span class="wplnst-results-mark wplnst-results-mark-modified' .($row->modified? '' : ' wplnst-display-none').'">'.__('Modified', 'wplnst').'</span>';
271
  $mark_nofollow = '<span class="wplnst-results-mark wplnst-results-mark-nofollow' .($row->nofollow? '' : ' wplnst-display-none').'">nofollow</span>';
277
  $mark_protorel = '<span class="wplnst-results-mark wplnst-results-mark-protorel' .($row->protorel? '' : ' wplnst-display-none').'">'.__('Protocol relative', 'wplnst').'</span>';
278
  $mark_ignored = '<span class="wplnst-results-mark wplnst-results-mark-ignored' .($row->ignored? '' : ' wplnst-display-none').'">'.__('Ignored', 'wplnst').'</span>';
279
  $mark_redirs = '<span class="wplnst-results-mark wplnst-results-mark-redirs' .($redirs? '' : ' wplnst-display-none').'">'.((!$redirs || empty($redirs_count) || 1 == $redirs_count)? '1 redirect' : $redirs_count.' redirects').'</span>';
280
+
281
  // Add new row checking visibility
282
  $mark_visible = ($row->modified || $row->nofollow || $row->relative || $row->absolute || $row->spaced || $row->malformed || $is_https || $row->protorel || $row->ignored || $redirs);
283
  $url .= '<div id="wplnst-results-url-marks-'.$row->loc_id.'" class="wplnst-results-url-marks'.($mark_visible? '' : ' wplnst-display-none').'">'.$mark_modified.$mark_nofollow.$mark_relative.$mark_absolute.$mark_spaced.$mark_malformed.$mark_https.$mark_protorel.$mark_ignored.$mark_redirs.'</div>';
284
+
285
+
286
  // Done
287
  $item['wplnst-url'] = '<div class="wplnst-row-url">'.$url.'</div>';
288
+
289
+
290
+
291
  /* Second column: status, redirection status, and time/size info */
292
+
293
  // Start container
294
  $item['wplnst-status'] = '<div class="wplnst-url-status-code">';
295
+
296
  // Prepare status classes
297
  $class_status_error = empty($row->curl_errno)? ' wplnst-display-none' : '';
298
  $class_status_code = empty($row->status_code)? ' wplnst-display-none' : '';
299
+
300
  // Prepare status Code
301
  $status_code_label = isset($status_codes[$row->status_code])? ' '.$status_codes[$row->status_code] : '';
302
+
303
  // Prepare rechecked mark
304
  $mark_rechecked = ' &nbsp; <span id="wplnst-url-status-recheck-mark-'.$row->loc_id.'" class="wplnst-results-mark wplnst-results-mark-rechecked'.($row->rechecked? '' : ' wplnst-display-none').'">Rechecked</span>';
305
+
306
  // Status code result
307
  $item['wplnst-status'] .= '<div class="wplnst-url-status-code-result"><span id="wplnst-url-status-code-0-loc-'.$row->loc_id.'" class="wplnst-url-status-code-0'.$class_status_error.'">'.__('Request error', 'wplnst').'</span><span id="wplnst-url-status-code-loc-'.$row->loc_id.'" class="wplnst-url-status-code-'.esc_attr($row->status_level).$class_status_code.'">'.esc_html($row->status_code.$status_code_label).'</span>'.$mark_rechecked.'</div>';
308
+
309
  // Prepare redirections status
310
  $redir_status_level = $redir_status_label = '';
311
  $status_redir = (!empty($row->redirect_url_id) && (!empty($row->redirect_url_status) || !empty($row->redirect_curl_errno)));
313
  $redir_status_level = mb_substr($row->redirect_url_status, 0, 1);
314
  $redir_status_label = $row->redirect_url_status.(isset($status_codes[$row->redirect_url_status])? ' '.$status_codes[$row->redirect_url_status] : '');
315
  }
316
+
317
  // Prepare redirection classes
318
  $class_status_redir = $status_redir? '' : ' wplnst-display-none';
319
  $class_status_redir_error = ($status_redir && !empty($row->redirect_curl_errno))? '' : ' wplnst-display-none';
320
  $class_status_redir_code = ($status_redir && !empty($row->redirect_url_status))? '' : ' wplnst-display-none';
321
+
322
  // Redirection status code
323
  $item['wplnst-status'] .= '<div id="wplnst-url-status-code-redir-'.$row->loc_id.'" class="wplnst-url-status-code-redir'.$class_status_redir.'"><span class="wplnst-url-status-code-redir-arrow">&rarr;&nbsp;</span><span id="wplnst-url-status-code-redir-error-'.$row->loc_id.'" class="wplnst-url-status-code-0'.$class_status_redir_error.'">'.__('Request error', 'wplnst').'</span><span id="wplnst-url-status-code-redir-status-'.$row->loc_id.'" class="wplnst-url-status-code-'.esc_attr($redir_status_level).$class_status_redir_code.'">'.esc_html($redir_status_label).'</span></div>';
324
+
325
  // End status container
326
  $item['wplnst-status'] .= '</div>';
327
+
328
  // Time and size
329
  $item['wplnst-status'] .= '<div class="wplnst-url-status-info"><span id="wplnst-url-status-info-time-'.$row->loc_id.'">'.number_format_i18n($row->total_time, 3).' s</span>'.(($row->total_bytes > 0)? '<span id="wplnst-url-status-info-split-'.$row->loc_id.'" class="wplnst-url-status-info-split"> | </span><span id="wplnst-url-status-info-size-'.$row->loc_id.'">'.wplnst_format_bytes($row->total_bytes).'</span>' : '<span id="wplnst-url-status-info-split-'.$row->loc_id.'" class="wplnst-url-status-info-split wplnst-display-none"> | </span><span id="wplnst-url-status-info-size-'.$row->loc_id.'" class="wplnst-display-none"></span>').'</div>';
330
+
331
+
332
+
333
  /* Third column: anchor text */
334
+
335
  // Set text anchor
336
  if ('links' == $row->link_type) {
337
+
338
  // Prepare modified mark
339
  $mark_anchored = '<div id="wplnst-results-anchor-mod-'.$row->loc_id.'" class="wplnst-results-anchor-mod'.($row->anchored? '' : ' wplnst-display-none').'"><span class="wplnst-results-mark wplnst-results-mark-modified">'.__('Modified', 'wplnst').'</span></div>';
340
+
341
  // Anchor text
342
  $item['wplnst-anchor'] = '<div class="wplnst-anchor-link"><span id="wplnst-results-anchor-loc-'.$row->loc_id.'">'.esc_html($row->anchor).'</span>'.$mark_anchored.'</div>';
343
+
344
  // Is an image
345
  } elseif ('images' == $row->link_type) {
346
 
347
  // Image info
348
  $item['wplnst-anchor'] = '<div class="wplnst-anchor-image wplnst-row-dashicon"><span>'.esc_html(__('Image', 'wplnst')).'</span></div>';
349
  }
350
+
351
+
352
+
353
  /* Fourth column: Content host */
354
+
355
  // Check no isolated
356
  if (!$this->results->isolated) {
357
+
358
  // Default content link
359
  $item['wplnst-content'] = $row->object_type.' '.$row->object_id;
360
+
361
  // Extract identifier
362
  $object_id = (int) $row->object_id;
363
+
364
  // Column content for posts
365
  if ('posts' == $row->object_type) {
366
+
367
+ // Retrieve post
368
  $post = get_post($object_id);
369
+
370
  // Check post object
371
  if (!empty($post) && is_object($post) && 'WP_Post' == get_class($post)) {
372
+
373
  // Copy object
374
  $item['post'] = $post;
375
  $item['can_edit'] = current_user_can('edit_post', $post->ID);
376
+
377
  // Prepare title
378
  $title = _draft_or_post_title($post);
379
+
380
  // Check edit post link
381
  if ($item['can_edit'] && 'trash' != $post->post_status) {
382
+
383
  // Copy edit post link
384
  $item['edit_post_link'] = get_edit_post_link($post->ID);
385
+
386
  // Editable post link
387
  $post_row = '<strong><a href="'.$item['edit_post_link'].'" title="'.esc_attr(sprintf(__( 'Edit &#8220;%s&#8221;'), $title)).'" target="_blank">'.$title.'</a></strong>';
388
+
389
  // Post without link
390
  } else {
391
+
392
  // Only title
393
  $post_row = '<strong>'.$title.'</strong>';
394
  }
395
+
396
  // Not found
397
  } else {
398
+
399
  // Not found item
400
  $post_row = sprintf(__('Entry %d not found', 'wplnst'), $object_id);
401
  }
402
+
403
  // Set column value
404
  $item['wplnst-content'] = '<div class="wplnst-content-post wplnst-row-dashicon"><span>'.$post_row.'</span></div>';
405
+
406
  // Column content for comments
407
  } elseif ('comments' == $row->object_type) {
408
+
409
  // Retrieve comment
410
  $object_id = (int) $row->object_id;
411
  $comment = get_comment($object_id);
412
+
413
  // Check comment object
414
  if (!empty($comment) && is_object($comment)) {
415
+
416
  // Copy object
417
  $item['comment'] = $comment;
418
  $item['can_edit'] = current_user_can('edit_comment', $comment->comment_ID);
419
+
420
  // Isolate comment author
421
  $comment_author = ('' === $comment->comment_author)? '' : '<strong>'.esc_html($comment->comment_author).'</strong> &#8212; ';
422
+
423
  // First comment chars
424
  $comment_text = wplnst_crop_text($comment->comment_content, 50);
425
+
426
  // Check editable comment
427
  if ($item['can_edit']) {
428
+
429
  // Submitted on link
430
  $comment_row = '<a href="'.admin_url('comment.php?action=editcomment&c='.$comment->comment_ID).'">'.$comment_author.$comment_text.'</a>';
431
+
432
  // Check approved comment
433
  } elseif ('approved' == wp_get_comment_status($comment->comment_ID)) {
434
+
435
  // View comment
436
  $comment_row = '<a href="'.esc_url(get_comment_link($comment->comment_ID)).'" target="_blank">'.$comment_author.$comment_text.'</a>';
437
+
438
  // No link
439
  } else {
440
+
441
  // Only text
442
  $comment_row = $comment_author.$comment_text;
443
  }
444
+
445
  // Not found
446
  } else {
447
+
448
  // Not found item
449
  $comment_row = sprintf(__('Comment %d not found', 'wplnst'), $object_id);
450
  }
451
+
452
  // Set column value
453
  $item['wplnst-content'] = '<div class="wplnst-content-comment wplnst-row-dashicon"><span>'.$comment_row.'</span></div>';
454
+
455
  // Column content for links
456
  } elseif ('blogroll' == $row->object_type) {
457
+
458
  // Retrieve link
459
  $object_id = (int) $row->object_id;
460
  $bookmark = get_bookmark($object_id);
461
+
462
  // Check link object
463
  if (!empty($bookmark) && is_object($bookmark)) {
464
+
465
  // Copy object
466
  $item['bookmark'] = $bookmark;
467
  $item['can_edit'] = current_user_can('manage_links', $bookmark->link_id);
468
+
469
  // Prepare visible URL
470
  $link_url = esc_html(url_shorten($bookmark->link_url));
471
+
472
  // Check editable comment
473
  if ($item['can_edit']) {
474
+
475
  // Submitted on link
476
  $bookmark_row = '<a href="'.admin_url('link.php?action=edit&link_id='.((int) $bookmark->link_id)).'" target="_blank">'.$link_url.'</a>';
477
+
478
  // No link
479
  } else {
480
+
481
  // Only text
482
  $bookmark_row = '<a href="'.esc_url($link->link_url).'" target="_blank" target="_blank">'.$link_url.'</a>';
483
  }
484
+
485
  // Not found
486
  } else {
487
+
488
  // Not found item
489
  $bookmark_row = sprintf(__('Bookmark %d not found', 'wplnst'), $object_id);
490
  }
491
+
492
  // Set column value
493
  $item['wplnst-content'] = '<div class="wplnst-content-bookmark wplnst-row-dashicon"><span>'.$bookmark_row.'</span></div>';
494
  }
495
  }
496
+
497
  // Add row
498
  $this->items[] = $item;
499
  }
539
  * @return mixed
540
  */
541
  protected function column_default($item, $column_name) {
542
+
543
  // Actions for URL column
544
  if ('wplnst-url' == $column_name) {
545
+
546
  // URL actions row
547
  $actions = $this->column_actions_url($item);
548
+ if (!empty($actions) && is_array($actions)) {
549
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
550
+ }
551
+
552
  // Actions for status column
553
  } elseif ('wplnst-status' == $column_name) {
554
+
555
  // Status actions row
556
  $actions = $this->column_actions_status($item);
557
+ if (!empty($actions) && is_array($actions)) {
558
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
559
+ }
560
+
561
  // Actions for the link anchor
562
  } elseif ('wplnst-anchor' == $column_name) {
563
+
564
  // Check links type and available anchor
565
  if ('links' == $item['link_type'] && false === strpos($item['object_field'], 'custom_field_url_')) {
566
+
567
  // Anchor actions row
568
  $actions = $this->column_actions_anchor($item);
569
+ if (!empty($actions) && is_array($actions)) {
570
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
571
+ }
572
  }
573
+
574
  // Actions for content column
575
  } elseif ('wplnst-content' == $column_name) {
576
+
577
  // Posts actions
578
  if ('posts' == $item['object_type']) {
579
+
580
  // Content post actions row
581
  $actions = $this->column_actions_content_posts($item);
582
+ if (!empty($actions) && is_array($actions)) {
583
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
584
+ }
585
+
586
  // Comments actions
587
  } elseif ('comments' == $item['object_type']) {
588
+
589
  // Content comments actions row
590
  $actions = $this->column_actions_content_comments($item);
591
+ if (!empty($actions) && is_array($actions)) {
592
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
593
+ }
594
+
595
  // Blogroll actions
596
  } elseif ('blogroll' == $item['object_type']) {
597
+
598
  // Content bookmarks actions row
599
  $actions = $this->column_actions_content_blogroll($item);
600
+ if (!empty($actions) && is_array($actions)) {
601
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions, $item['loc_id']));
602
+ }
603
  }
604
  }
605
+
606
  // Default column
607
  return $item[$column_name];
608
  }
613
  * Column URL row actions
614
  */
615
  private function column_actions_url($item) {
616
+
617
  // Initialize
618
  $actions = array();
619
+
620
  // For not isolated
621
  if (!$this->results->isolated) {
622
+
623
  // Check object
624
  if (isset($item['can_edit']) && $item['can_edit']) {
625
+
626
  // Add results actions
627
+ $actions = apply_filters('wplnst_results_actions_url', $actions, $item);
628
  }
629
+
630
  // Filter by URL (for future versions)
631
  // $actions['wplnst-action-filter'] = '<a href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_locations($this->results->scan->id, $item['url_id'])).'" class="wplnst-results-action">'.__('Filter by URL', 'wplnst').'</a>';
632
  }
633
+
634
  // Done
635
  return $actions;
636
  }
641
  * Column Status row actions
642
  */
643
  private function column_actions_status($item) {
644
+
645
  // Initialize
646
  $actions = array();
647
+
648
  // For not isolated
649
  if (!$this->results->isolated) {
650
+
651
  // Add results actions
652
  $actions = apply_filters('wplnst_results_actions_status', $actions, $item);
653
  }
654
+
655
  // Done
656
  return $actions;
657
  }
662
  * Column Anchor row actions
663
  */
664
  private function column_actions_anchor($item) {
665
+
666
  // Initialize
667
  $actions = array();
668
+
669
  // For not isolated
670
  if (!$this->results->isolated) {
671
+
672
  // Check editable object
673
  if (isset($item['can_edit']) && $item['can_edit']) {
674
+
675
  // Add results actions
676
  $actions = apply_filters('wplnst_results_actions_anchor', $actions, $item);
677
  }
678
  }
679
+
680
  // Done
681
  return $actions;
682
  }
687
  * Column content row actions for posts
688
  */
689
  private function column_actions_content_posts($item) {
690
+
691
  // Check object
692
  if (!isset($item['post']))
693
  return array();
694
+
695
  // Initialize
696
  $actions = array();
697
  $post = $item['post'];
698
+
699
  // Permissions
700
  $can_edit_post = $item['can_edit'];
701
  $post_type_object = get_post_type_object($post->post_type);
702
+
703
  // Check edit post action
704
+ if ($can_edit_post && 'trash' != $post->post_status) {
705
  $actions['edit'] = '<a href="'.$item['edit_post_link'].'" title="'.esc_attr__('Edit this item').'" target="_blank">'.__( 'Edit' ).'</a>';
706
+ }
707
+
708
  // Check delete post action
709
  if (current_user_can('delete_post', $post->ID)) {
710
+
711
  // Post in trash
712
+ if ('trash' == $post->post_status) {
713
  $actions['untrash'] = "<a title='" . esc_attr__( 'Restore this item from the Trash' ) . "' href='" . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore' ) . "</a>";
714
+
715
  // Post to trash
716
+ } elseif (EMPTY_TRASH_DAYS) {
717
  $actions['trash'] = "<a class='submitdelete' title='".esc_attr__('Move this item to the Trash')."' href='".get_delete_post_link($post->ID)."'>".__('Trash')."</a>";
718
+ }
719
+
720
  // Remove Permanently
721
+ if ('trash' == $post->post_status || !EMPTY_TRASH_DAYS) {
722
  $actions['delete'] = "<a class='submitdelete wplnst-remove-entry' title='".esc_attr__('Delete this item permanently')."' href='".get_delete_post_link($post->ID, '', true)."'>".__('Delete Permanently')."</a>";
723
+ }
724
  }
725
+
726
  // Check view post action
727
  if ($post_type_object->public) {
728
+
729
  // Post title
730
  $title = _draft_or_post_title();
731
+
732
  // Not published
733
  if (in_array($post->post_status, array('pending', 'draft', 'future'))) {
734
  if ($can_edit_post) {
737
  $preview_link = apply_filters( 'preview_post_link', add_query_arg('preview', 'true', $preview_link ), $post );
738
  $actions['view'] = '<a href="' . esc_url( $preview_link ) . '" title="' . esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;' ), $title ) ) . '" rel="permalink" target="_blank">' . __( 'Preview' ) . '</a>';
739
  }
740
+
741
  // Not in trash
742
  } elseif ( 'trash' != $post->post_status ) {
743
  $actions['view'] = '<a href="' . get_permalink( $post->ID ) . '" title="' . esc_attr( sprintf( __( 'View &#8220;%s&#8221;' ), $title ) ) . '" rel="permalink" target="_blank">' . __( 'View' ) . '</a>';
744
  }
745
  }
746
+
747
  // Done
748
  return $actions;
749
  }
754
  * Column content row actions for comments
755
  */
756
  private function column_actions_content_comments($item) {
757
+
758
  // Check object
759
  if (!isset($item['comment']))
760
  return array();
761
+
762
  // Initialize
763
  $actions = array();
764
  $comment = $item['comment'];
765
+
766
  // Check editable comment
767
  if ($item['can_edit']) {
768
+
769
  // Real comment status
770
  $the_comment_status = wp_get_comment_status($comment->comment_ID);
771
+
772
  // Remove and approve nonces
773
  $del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) );
774
  $approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) );
775
+
776
  // Base URL
777
  $url = "comment.php?c=$comment->comment_ID";
778
+
779
  // All URLs
780
  $approve_url = esc_url( $url . "&action=approvecomment&$approve_nonce" );
781
  $unapprove_url = esc_url( $url . "&action=unapprovecomment&$approve_nonce" );
784
  $trash_url = esc_url( $url . "&action=trashcomment&$del_nonce" );
785
  $untrash_url = esc_url( $url . "&action=untrashcomment&$del_nonce" );
786
  $delete_url = esc_url( $url . "&action=deletecomment&$del_nonce" );
787
+
788
  // Preorder it: Edit | Approve | Spam | Trash.
789
  $actions = array(
790
  'edit' => '',
798
  } elseif ( 'unapproved' == $the_comment_status ) {
799
  $actions['approvecomment'] = "<a href='$approve_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID:e7e7d3:action=dim-comment&amp;new=approved' class='vim-a vim-destructive' title='" . esc_attr__( 'Approve this comment' ) . "'>" . __( 'Approve' ) . '</a>';
800
  }
801
+
802
  if ( 'spam' != $the_comment_status ) {
803
  $actions['spam'] = "<a href='$spam_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::spam=1' class='vim-s vim-destructive' title='" . esc_attr__( 'Mark this comment as spam' ) . "'>" . /* translators: mark as spam link */ _x( 'Spam', 'verb' ) . '</a>';
804
  } elseif ( 'spam' == $the_comment_status ) {
805
  $actions['unspam'] = "<a href='$unspam_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID:66cc66:unspam=1' class='vim-z vim-destructive'>" . _x( 'Not Spam', 'comment' ) . '</a>';
806
  }
807
+
808
  if ( 'trash' == $the_comment_status ) {
809
  $actions['untrash'] = "<a href='$untrash_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID:66cc66:untrash=1' class='vim-z vim-destructive'>" . __( 'Restore' ) . '</a>';
810
  }
811
+
812
  if ( 'spam' == $the_comment_status || 'trash' == $the_comment_status || !EMPTY_TRASH_DAYS ) {
813
  $actions['delete'] = "<a href='$delete_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::delete=1' class='delete vim-d vim-destructive wplnst-remove-comment'>" . __( 'Delete Permanently' ) . '</a>';
814
  } else {
815
  $actions['trash'] = "<a href='$trash_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::trash=1' class='delete vim-d vim-destructive' title='" . esc_attr__( 'Move this comment to the trash' ) . "'>" . _x( 'Trash', 'verb' ) . '</a>';
816
  }
817
+
818
+ if ('spam' != $the_comment_status && 'trash' != $the_comment_status) {
819
  $actions['edit'] = "<a href='comment.php?action=editcomment&amp;c={$comment->comment_ID}' title='" . esc_attr__( 'Edit comment' ) . "'>". __( 'Edit' ) . '</a>';
820
+ }
821
  }
822
+
823
  // Check approved comment to see it
824
+ if ('approved' == wp_get_comment_status($comment->comment_ID)) {
825
  $actions['view'] = '<a href="'.esc_url(get_comment_link($comment->comment_ID)).'" target="_blank">'.__('View').'</a>';
826
+ }
827
+
828
  /** This filter is documented in wp-admin/includes/dashboard.php */
829
  $actions = apply_filters('comment_row_actions', array_filter($actions), $comment);
830
+
831
  // Done
832
  return $actions;
833
  }
838
  * Column content row actions for blogroll
839
  */
840
  private function column_actions_content_blogroll($item) {
841
+
842
  // Check object
843
+ if (!isset($item['bookmark'])) {
844
  return array();
845
+ }
846
+
847
  // Initialize
848
  $actions = array();
849
  $bookmark = $item['bookmark'];
850
+
851
  // Check editable comment
852
  if ($item['can_edit']) {
853
+
854
  // Cast identifier
855
  $bookmark_id = (int) $bookmark->link_id;
856
+
857
  // Edit or remove link
858
  $actions['edit'] = '<a href="'.admin_url('link.php?action=edit&link_id='.$bookmark_id).'" target="_blank">'.__('Edit').'</a>';
859
  $actions['trash'] = '<a class="wplnst-remove-bookmark" href="'.wp_nonce_url('link.php?action=delete&link_id='.$bookmark_id, 'delete-bookmark_'.$bookmark_id).'" target="_blank">'.__('Delete').'</a>';
860
  }
861
+
862
  // Visit action
863
  $actions['visit'] = '<a href="'.esc_url($bookmark->link_url).'" target="_blank">'.__('Visit', 'wplnst').'</a>';
864
+
865
  // Done
866
  return $actions;
867
  }
879
  * @return string
880
  */
881
  protected function row_actions( $actions, $loc_id = 0 ) {
882
+
883
  $action_count = count( $actions );
884
  $i = 0;
885
+
886
+ if ( !$action_count ) {
887
  return '';
888
+ }
889
+
890
  $out = '<div class="row-actions wplnst-row-actions wplnst-row-actions-'.$loc_id.'">';
891
  foreach ( $actions as $action => $link ) {
892
  ++$i;
894
  $out .= "<span class='$action'>$link$sep</span>";
895
  }
896
  $out .= '</div>';
897
+
898
  return $out;
899
  }
900
 
925
  * @access public
926
  */
927
  public function display() {
928
+
929
  // Wrapper form
930
  echo '<form method="get" action="'.esc_url(remove_query_arg('paged', set_url_scheme('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']))).'" id="wplnst-results" data-nonce="'.esc_attr(wp_create_nonce('wplnst-results-'.$this->results->scan->hash)).'" data-nonce-advanced-display="'.esc_attr(wp_create_nonce('wplnst-results-advanced-display')).'" data-confirm-delete-entry="'.esc_attr__('Please, confirm you want to remove this entry pressing the Ok button', 'wplnst').'" data-confirm-delete-comment="'.esc_attr__('Please, confirm you want to remove this comment pressing the Ok button', 'wplnst').'" data-confirm-delete-bookmark="'.esc_attr__('Please, confirm you want to remove this bookmark pressing the Ok button', 'wplnst').'" data-label-action-url-redir="'.esc_attr__('Apply Redirection', 'wplnst').'" data-label-server-comm-error="'.esc_attr(WPLNST_Core_Text::get_text('server_comm_error')).'" data-label-unknown-error="'.esc_attr(WPLNST_Core_Text::get_text('unknown_error')).'" data-label-select-any="'.esc_attr__('Please, select any result to proceed', 'wplnst').'" data-label-error-code="'.esc_attr__('error code', 'wplnst').'">';
931
+
932
  // Hidden fields
933
  echo '<input type="hidden" name="page" value="'.esc_attr($_GET['page']).'" />';
934
  echo '<input type="hidden" name="scan_id" value="'.esc_attr($this->results->scan->id).'" />';
935
  echo '<input type="hidden" name="context" value="results" />';
936
  if (isset($this->results->status_level)) echo '<input type="hidden" name="status" value="'.esc_attr($this->results->status_level).'" />';
937
+
938
  // Raise event at this point
939
  do_action('wplnst_scans_results_view_display');
940
+
941
  // Check isolated classes
942
  $extra_classes = array();
943
+ if ($this->results->isolated) {
944
  $extra_classes[] = 'wplnst-isolated-table';
945
+ }
946
+
947
  // Show levels menu
948
  $this->menu();
949
+
950
  // Check isolated display
951
+ if (!$this->results->isolated) {
952
  $this->display_tablenav('top');
953
+ }
954
+
955
  ?><table class="wp-list-table <?php echo implode(' ', array_merge($this->get_table_classes(), $extra_classes)); ?>">
956
  <thead>
957
  <tr>
969
  </tfoot>
970
  <?php endif; ?>
971
  </table><?php
972
+
973
  // Check isolated display
974
+ if (!$this->results->isolated) {
975
  $this->display_tablenav('bottom');
976
+ }
977
+
978
  // Close form
979
  echo '</form>';
980
  }
1003
  * Display a menu based on status levels
1004
  */
1005
  private function menu() {
1006
+
1007
  // Initialize
1008
  $status_levels = WPLNST_Core_Types::get_status_levels();
1009
+
1010
  // Enum summary elements
1011
  $levels = array();
1012
  foreach ($this->results->scan->summary as $key => $value) {
1013
+
1014
  // Status level record
1015
  if (0 === strpos($key, 'status_level_')) {
1016
  $key = explode('status_level_', $key);
1024
  }
1025
  }
1026
  }
1027
+
1028
  // Status levels menu
1029
  $menu_levels = array();
1030
  foreach ($status_levels as $key => $label) {
1031
+ if (in_array($key, array_keys($levels))) {
1032
  $menu_levels[$key] = $levels[$key];
1033
+ }
1034
  }
1035
+
1036
  // Check stored total
1037
  $total = empty($this->results->scan->summary['status_total'])? 0 : (int) $this->results->scan->summary['status_total'];
1038
+
1039
  // Menu levels
1040
  $menu_links = array();
1041
+
1042
  // All results
1043
  $menu_links[] = '<a href="'.$this->base_url.'"'.($total > 0 && $this->results->is_all_results? ' class="current"' : '').'>'.__('All results', 'wplnst').' </a><span class="count">('.($this->results->is_all_results? number_format_i18n($this->results->total_rows) : number_format_i18n($total)).')</span>';
1044
+
1045
  // Request error
1046
+ if (!empty($levels['0'])) {
1047
  $menu_links[] = '<a href="'.$this->base_url.'&status=0"'.(('0' === $this->results->status_level && !$this->results->is_search)? ' class="current"' : '').'>'.__('Request error', 'wplnst').' </a><span class="count">('.number_format_i18n($levels['0']).')</span>';
1048
+ }
1049
+
1050
  // Level results
1051
+ foreach ($menu_levels as $key => $total) {
1052
  $menu_links[] = '<a href="'.$this->base_url.'&status='.$key.'"'.(($key == $this->results->status_level && !$this->results->is_search)? ' class="current"' : '').'>'.esc_html($key.'00s '.$status_levels[$key]).' </a><span class="count">('.number_format_i18n($total).')</span>';
1053
+ }
1054
+
1055
  // Show menu
1056
  echo '<div id="wplnst-levels-menu" class="wplnst-clearfix'.($this->results->isolated? ' wplnst-levels-menu-isolated' : '').'"><ul class="subsubsub"><li>'.implode(' | </li><li>', $menu_links).'</li></ul>'.(('end' != $this->results->scan->status)? '<div class="alignright wplnst-aproximate-total">'.__('(counters in progress)', 'wplnst').'</div>' : '').'</div>';
1057
  }
1062
  * Display a set of filters
1063
  */
1064
  protected function filters() {
1065
+
1066
  // Check filters
1067
  $fields = $this->filters_fields();
1068
+ if (empty($fields)) {
1069
  return;
1070
+ }
1071
+
1072
  // Show menu, actions, etc.
1073
  echo '<div id="wplnst-results-filters" class="alignleft actions'.$this->filters_classes().'">';
1074
+
1075
  // Display fields
1076
+ foreach ($fields as $key => $field) {
1077
  echo '<select id="wplnst-filter-'.$key.'"><option value="">'.esc_html($field['title']).'</option>'.$field['options'].'</select>';
1078
+ }
1079
+
1080
  // Button and end of div
1081
  echo '&nbsp;<input id="wplnst-filter-button" data-fields="'.implode(',', array_keys($fields)).'" data-href="'.esc_attr($this->base_url).'" class="button" type="button" value="'.__('Filter', 'wplnst').'" /></div>';
1082
  }
1096
  * Retrieve fields for basic filters
1097
  */
1098
  protected function filters_fields() {
1099
+
1100
  // Basic fields
1101
  $fields = array();
1102
+
1103
+
1104
  /* Status codes filter */
1105
+
1106
  // Initialize
1107
  $objects_types = WPLNST_Core_Types::get_objects_types();
1108
  $status_levels = WPLNST_Core_Types::get_status_levels();
1109
  $status_codes_raw = WPLNST_Core_Types::get_status_codes_raw();
1110
+
1111
  // Enum summary elements
1112
  $levels = $codes = $objects = array();
1113
  foreach ($this->results->scan->summary as $key => $value) {
1114
+
1115
  // Status codes
1116
  if (0 === strpos($key, 'status_code_')) {
1117
  $key = explode('status_code_', $key);
1121
  $levels['0'] = true;
1122
  } elseif (3 == strlen($key) && isset($status_codes_raw[$key])) {
1123
  $level = substr($key, 0, 1);
1124
+ if (isset($status_levels[$level])) {
1125
  $levels[$level] = isset($levels[$level])? $levels[$level] + 1 : 1;
1126
+ }
1127
  $codes[$key] = $value;
1128
  }
1129
  }
1130
+
1131
  // Objects match
1132
  } elseif (0 === strpos($key, 'objects_match_')) {
1133
  $key = explode('objects_match_', $key);
1134
+ if (2 == count($key) && in_array($key[1], array_keys($objects_types))) {
1135
  $objects[$key[1]] = $value;
1136
+ }
1137
  }
1138
  }
1139
+
1140
+
1141
  /* Status codes options */
1142
+
1143
  // Collect options
1144
  $options_codes = empty($levels['0'])? '' : '<option '.((isset($this->results->status_level) && '0' === $this->results->status_level)? 'selected' : '').' value="0">'.__('Request error', 'wplnst').'</option>';
1145
  $options_levels = array();
1153
  $options_codes .= '<option '.((!empty($this->results->status_code) && $this->results->status_code == $key)? 'selected' : '').' value="'.$key.'">'.$key.' '.$label.'</option>';
1154
  }
1155
  }
1156
+
1157
  // Add filter
1158
  $fields['status'] = array(
1159
  'type' => 'select',
1160
  'title' => __('All status codes', 'wplnst'),
1161
  'options' => $options_codes,
1162
  );
1163
+
1164
+
1165
  /* Objects options */
1166
+
1167
  // Collect custom post types
1168
  $options_post_types = '';
1169
  if (in_array('posts', array_keys($objects))) {
1170
  $post_types = WPLNST_Core_Types::get_post_types();
1171
  foreach ($post_types as $type => $name) {
1172
+ if (in_array($type, $this->results->scan->post_types)) {
1173
  $options_post_types .= '<option '.((!empty($this->results->object_post_type) && $this->results->object_post_type == $type)? 'selected' : '').' value="posts_'.$type.'">&mdash;'.esc_html($name).'</option>';
1174
+ }
1175
  }
1176
  }
1177
+
1178
  // Collect options
1179
  $objects_codes = '';
1180
  foreach ($objects_types as $key => $value) {
1181
  if (in_array($key, array_keys($objects))) {
1182
  $objects_codes .= '<option '.((!empty($this->results->object_type) && $this->results->object_type == $key)? 'selected' : '').' value="'.$key.'">'.$value.'</option>';
1183
+ if ('posts' == $key) {
1184
  $objects_codes .= $options_post_types;
1185
+ }
1186
  }
1187
  }
1188
+
1189
  // Check filter
1190
  $fields['otype'] = array(
1191
  'type' => 'select',
1192
  'title' => __('All content', 'wplnst'),
1193
  'options' => $objects_codes,
1194
  );
1195
+
1196
+
1197
  /* Options for link types */
1198
+
1199
  $options_ltypes = '';
1200
  $link_types = WPLNST_Core_Types::get_link_types();
1201
+ foreach ($link_types as $link_type => $link_type_name) {
1202
  $options_ltypes .= '<option '.((!empty($this->results->link_type) && $this->results->link_type == $link_type)? 'selected' : '').' value="'.esc_attr($link_type).'">'.esc_html($link_type_name).'</option>';
1203
+ }
1204
+
1205
  // Check filter
1206
  $fields['ltype'] = array(
1207
  'type' => 'select',
1208
  'title' => __('All link types', 'wplnst'),
1209
  'options' => $options_ltypes,
1210
  );
1211
+
1212
+
1213
  // Done
1214
  return $fields;
1215
  }
views/scans.php CHANGED
@@ -1,18 +1,20 @@
1
  <?php
2
 
3
  // Check WP constant
4
- if (!defined('ABSPATH'))
5
  die;
 
6
 
7
  // Check dependencies
8
- if(!class_exists('WP_List_Table'))
9
- require_once(ABSPATH.'wp-admin/includes/class-wp-list-table.php');
 
10
 
11
  /**
12
- * WP Link Status Views Scans class
13
  *
14
  * @package WP Link Status
15
- * @subpackage WP Link Status Views
16
  */
17
  class WPLNST_Views_Scans extends WP_List_Table {
18
 
@@ -45,13 +47,13 @@ class WPLNST_Views_Scans extends WP_List_Table {
45
  * Constructor
46
  */
47
  public function __construct($results) {
48
-
49
  // Parent constructor
50
  parent::__construct();
51
-
52
  // Copy results
53
  $this->results = $results;
54
-
55
  // Base link for filters
56
  $this->base_url = esc_url(WPLNST_Core_Plugin::get_url_scans());
57
  }
@@ -62,13 +64,13 @@ class WPLNST_Views_Scans extends WP_List_Table {
62
  * Prepare columns and data
63
  */
64
  function prepare_items() {
65
-
66
  // Columns
67
  $this->setup_columns();
68
-
69
  // Data items
70
  $this->setup_items();
71
-
72
  // Pagination
73
  $this->setup_pagination();
74
  }
@@ -83,7 +85,7 @@ class WPLNST_Views_Scans extends WP_List_Table {
83
  // Initialize
84
  $hidden = array();
85
  $sortable = array();
86
-
87
  // Column headers
88
  $this->_column_headers = array($this->get_columns(), $hidden, $sortable);
89
  }
@@ -94,12 +96,13 @@ class WPLNST_Views_Scans extends WP_List_Table {
94
  * Columns array
95
  */
96
  public function get_columns(){
97
-
98
  // Checkbox column
99
  $columns = array();
100
- if (!$this->results->isolated)
101
  $columns['cb'] = '<input type="checkbox" />';
102
-
 
103
  // All columns
104
  return array_merge($columns, array(
105
  'wplnst-scans-name' => __('Scan info', 'wplnst'),
@@ -113,37 +116,37 @@ class WPLNST_Views_Scans extends WP_List_Table {
113
  * Setup data items
114
  */
115
  private function setup_items() {
116
-
117
  // Initialize
118
  $this->items = array();
119
-
120
  // Warning image
121
  $warning_img = '<img src="'.plugins_url('assets/images/scan-warning.png', WPLNST_FILE).'" width="16" height="16" border="0" style="margin-right: 5px;" title="'.__('Some critical values of this scan are not completed', 'wplnst').'">';
122
-
123
  // Populate data
124
  foreach ($this->results->rows as $scan) {
125
-
126
  // Initialize
127
  $timeinfo = false;
128
  $linksinfo = '';
129
-
130
  // Normalize identifiers and other data
131
  $item = array('ID' => $scan->id, 'hash' => $scan->hash, 'status' => $scan->status, 'ready' => $scan->ready);
132
-
133
  // Check processed posts
134
  $message = ('play' != $scan->status)? '' : __('Waiting...', 'wplnst');
135
-
136
  // Initialize
137
  $processed = array();
138
  $running_back = false;
139
  $class_completed = ('end' == $scan->status)? 'wplnst-scan-object-completed-end' : 'wplnst-scan-object-completed';
140
-
141
  if (isset($scan->trace['total_posts'])) {
142
  $running_back = empty($scan->trace['populated_posts']);
143
  $posts_index = empty($scan->trace['posts_index'])? 0 : number_format_i18n($scan->trace['posts_index']);
144
  $processed[] = empty($scan->trace['populated_posts'])? '<span class="wplnst-scan-object-info wplnst-scan-object-running">'.$posts_index.'/'.number_format_i18n($scan->trace['total_posts']).' '.__('entries', 'wplnst').'</span>' : '<span class="wplnst-scan-object-info '.$class_completed.'">'.number_format_i18n($scan->trace['total_posts']).' '.__('entries', 'wplnst').'</span>';
145
  }
146
-
147
  if (isset($scan->trace['total_comments'])) {
148
  $running = !$running_back && empty($scan->trace['populated_comments']);
149
  $running_back = $running? true : $running_back;
@@ -151,142 +154,144 @@ class WPLNST_Views_Scans extends WP_List_Table {
151
  $comments_index = empty($scan->trace['comments_index'])? 0 : number_format_i18n($scan->trace['comments_index']);
152
  $processed[] = empty($scan->trace['populated_comments'])? '<span class="wplnst-scan-object-info '.$class_running.'">'.$comments_index.'/'.number_format_i18n($scan->trace['total_comments']).' '.__('comments', 'wplnst').'</span>' : '<span class="wplnst-scan-object-info '.$class_completed.'">'.number_format_i18n($scan->trace['total_comments']).' '.__('comments', 'wplnst').'</span>';
153
  }
154
-
155
  if (isset($scan->trace['total_blogroll'])) {
156
  $running = !$running_back && empty($scan->trace['populated_blogroll']);
157
  $class_running = $running? 'wplnst-scan-object-running' : 'wplnst-scan-object-wait';
158
  $blogroll_index = empty($scan->trace['blogroll_index'])? 0 : number_format_i18n($scan->trace['blogroll_index']);
159
  $processed[] = empty($scan->trace['populated_blogroll'])? '<span class="wplnst-scan-object-info '.$class_running.'">'.$blogroll_index.'/'.number_format_i18n($scan->trace['total_blogroll']).' '.__('blogroll', 'wplnst').'</span>' : '<span class="wplnst-scan-object-info '.$class_completed.'">'.number_format_i18n($scan->trace['total_blogroll']).' '.__('blogroll', 'wplnst').'</span>';
160
  }
161
-
162
  // Check info
163
  if (!empty($processed)) {
164
-
165
  // Processed object types
166
  $message = implode('&nbsp;', $processed);
167
-
168
  // Check status
169
  if ('wait' != $scan->status) {
170
-
171
-
172
  /* Time info */
173
-
174
  // Start and local extra time
175
  $time_start = strtotime($scan->row->started_at.' UTC');
176
  $offset_time = get_option('gmt_offset') * HOUR_IN_SECONDS;
177
-
178
  // Current dates
179
  $today_date = gmdate('d/m/Y', time() + $offset_time);
180
  $yesterday_date = gmdate('d/m/Y', time() + $offset_time - 86400);
181
-
182
  // Local date and hour
183
  $start_date = gmdate('d/m/Y', $time_start + $offset_time);
184
  $start_hour = gmdate('H:i', $time_start + $offset_time);
185
-
186
  // Check today
187
  if ($start_date == $today_date) {
188
-
189
  // Today
190
  $started_at = sprintf(__('Today from %s', 'wplnst'), $start_hour);
191
-
192
  // Check yesterday
193
  } elseif ($start_date == $yesterday_date) {
194
-
195
  // Yesterday
196
  $started_at = sprintf(__('Yesterday at %s', 'wplnst'), $start_hour);
197
-
198
  // Other
199
  } else {
200
-
201
  // Date and hour
202
  $started_at = sprintf(__('%s at %s', 'wplnst'), $start_date, $start_hour);
203
  }
204
-
205
  // Start date
206
  $timeinfo = $started_at;
207
-
208
  // Retrieve time stopped
209
  $time_stopped = isset($scan->summary['time_stopped'])? (int) $scan->summary['time_stopped'] : 0;
210
-
211
  // Ended scan
212
  if ('end' == $scan->status) {
213
-
214
  // Finished date
215
  $time_end = $time_end_amount = strtotime($scan->row->finished_at.' UTC');
216
-
217
  // Local date and hour
218
  $end_date = gmdate('d/m/Y', $time_end + $offset_time);
219
  $end_hour = gmdate('H:i', $time_end + $offset_time);
220
-
221
  // Check today
222
  if ($end_date == $today_date) {
223
-
224
  // All today
225
  if ($start_date == $today_date) {
226
-
227
  // Started and finished today
228
  $timeinfo .= ' '.sprintf(__('to %s', 'wplnst'), $end_hour);
229
-
230
  // Date to today
231
  } else {
232
-
233
  // Started another date and finished today
234
  $timeinfo .= ' '.sprintf(__('to today at %s', 'wplnst'), $end_hour);
235
  }
236
-
237
  // Check yesterday
238
  } elseif ($end_date == $yesterday_date) {
239
-
240
  // All yesterday
241
  if ($start_date == $yesterday_date) {
242
-
243
  // Started and finished today
244
  $timeinfo .= ' '.sprintf(__('to %s', 'wplnst'), $end_hour);
245
-
246
  // Date to yesterday
247
  } else {
248
-
249
  // Started another date and finished today
250
  $timeinfo .= ' '.sprintf(__('to yesterday at %s', 'wplnst'), $end_hour);
251
  }
252
-
253
  // Check same day
254
  } elseif ($end_date == $start_date) {
255
-
256
  // Same day
257
  $timeinfo .= ' '.sprintf(__('until %s', 'wplnst'), $end_hour);
258
-
259
  // Before
260
  } else {
261
-
262
  // Different days
263
  $timeinfo .= ' '.sprintf(__('until %s at %s', 'wplnst'), $end_date, $end_hour);
264
  }
265
-
266
  // Time stopped correction
267
- if (!empty($time_stopped))
268
  $time_end_amount -= $time_stopped;
269
-
 
270
  // Total time
271
  $timeinfo .= ' &#8212; '.human_time_diff($time_start, $time_end_amount);
272
-
273
  // Running
274
  } else {
275
-
276
  // Until now or stopped
277
  $time_end = ('stop' == $scan->status)? strtotime($scan->row->stopped_at.' UTC') : time();
278
-
279
  // Time stopped correction
280
- if (!empty($time_stopped))
281
  $time_end -= $time_stopped;
282
-
 
283
  // Elapsed time
284
  $timeinfo .= ' &#8212; '.sprintf(__('Running time %s', 'wplnst'), human_time_diff($time_start, $time_end));
285
  }
286
-
287
-
288
  /* Links info */
289
-
290
  // Normalize
291
  $phases = array();
292
  foreach ($scan->summary as $key => $value) {
@@ -295,115 +300,125 @@ class WPLNST_Views_Scans extends WP_List_Table {
295
  $phases[$phase[1]] = $value;
296
  }
297
  }
298
-
299
  // Check values
300
  if (!empty($phases)) {
301
-
302
  // Collect data
303
  $items = array();
304
-
305
  // All results
306
  $items[] = (isset($scan->summary['status_total']) && $scan->summary['status_total'] > 0)? sprintf(__('<strong>%s</strong> results', 'wplnst'), number_format_i18n((int) $scan->summary['status_total'])) : __('No results', 'wplnst');
307
-
308
  // Total processed
309
  if (!empty($phases['processed'])) {
310
-
311
  // Add uniques
312
  $items[] = sprintf(__('<strong>%s</strong> unique URLs', 'wplnst'), number_format_i18n((int) $phases['processed']));
313
  }
314
-
315
  // Enqueued URLs
316
- if ('end' != $scan->status)
317
  $items[] = sprintf(__('%s enqueued', 'wplnst'), (isset($phases['wait'])? number_format_i18n((int) $phases['wait']) : '0'));
318
-
 
319
  // Waiting
320
- if ('play' == $scan->status)
321
  $items[] = sprintf(__('%s processing', 'wplnst'), (empty($phases['play'])? wplnst_get_nsetting('max_threads', $scan->threads->max) : (int) $phases['play']));
322
-
 
323
  // End crawler
324
- if ('end' == $scan->status)
325
  $items[] = sprintf(__('<strong>%s</strong> Request error', 'wplnst'), (isset($scan->summary['status_level_0'])? (int) number_format_i18n($scan->summary['status_level_0']) : '0'));
326
-
 
327
  // Join items
328
- if (!empty($items))
329
  $linksinfo = implode('<span class="wplnst-split-char">&middot;</span>', $items);
 
330
  }
331
  }
332
-
333
  // Only created
334
  } elseif ('wait' == $scan->status || 'queued' == $scan->status || 'stop' == $scan->status) {
335
-
336
  // Created date
337
  $time_created = strtotime($scan->row->created_at.' UTC');
338
  $offset_time = get_option('gmt_offset') * HOUR_IN_SECONDS;
339
-
340
  // Current dates
341
  $today_date = gmdate('d/m/Y', time() + $offset_time);
342
  $yesterday_date = gmdate('d/m/Y', time() + $offset_time - 86400);
343
-
344
  // Local date and hour
345
  $created_date = gmdate('d/m/Y', $time_created + $offset_time);
346
  $created_hour = gmdate('H:i', $time_created + $offset_time);
347
-
348
  // Check today
349
  if ($created_date == $today_date) {
350
-
351
  // Created today
352
  $timeinfo = sprintf(__('Created today at %s', 'wplnst'), $created_hour);
353
-
354
  // Yesterday
355
  } elseif ($created_date == $yesterday_date) {
356
-
357
  // Created yesterday
358
  $timeinfo = sprintf(__('Created yesterday at %s', 'wplnst'), $created_hour);
359
-
360
  // Any date
361
  } else {
362
-
363
  // Created date and hour
364
  $timeinfo = sprintf(__('Created %s at %s', 'wplnst'), $created_date, $created_hour);
365
  }
366
  }
367
-
368
-
369
-
370
  // Item name, possible warning and link to edit
371
  $statuses = WPLNST_Core_Types::get_scan_statuses();
372
  $item['wplnst-scans-name'] = '<strong class="wplnst-scan-name'.($scan->ready? '' : ' wplnst-scan-name-warning').'">'.($scan->ready? '' : $warning_img);
373
- if ('wait' != $scan->status)
374
  $item['wplnst-scans-name'] .= '<span class="wplnst-scan-status wplnst-scan-status-'.esc_attr($scan->status).'">'.$statuses[$scan->status].'</span>&nbsp;';
 
375
  $item['wplnst-scans-name'] .= '<a class="row-title" href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan->id)).'">'.(empty($scan->name)? __('(no name)', 'wplnst') : esc_html($scan->name)).'</a></strong>';
376
  $item['wplnst-scans-name'] .= '<div class="wplnst-scan-status-line">'.$message.'</div>';
377
-
378
  // Check ready message
379
- if ('wait' == $scan->status && $scan->ready)
380
  $item['wplnst-scans-name'] .= '<div class="wplnst-scan-ready-info">'.sprintf(__('Ready to <a href="%s">start the crawler</a>', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($scan->id, 'on', $scan->hash))).'</div>';
381
-
 
382
  // Check datatime info
383
- if (!empty($timeinfo))
384
  $item['wplnst-scans-name'] .= '<div class="wplnst-scan-time-info">'.$timeinfo.'</div>';
385
-
 
386
  // Check links info
387
- if (!empty($linksinfo))
388
- $item['wplnst-scans-name'] .= '<div class="wplnst-scan-links-info">'.$linksinfo.'</div>';
389
-
390
-
 
391
  // Prepare configuration
392
  $item['wplnst-scans-configuration'] = '<table>';
393
-
394
  // Scan scope
395
  $link_types = (empty($scan->link_types_names)? '' : implode(', ', array_map('esc_html', $scan->link_types_names)));
396
- $item['wplnst-scans-configuration'] .= '<tr><td class="wplnst-scans-configuration-row"><strong>'.__('Scope', 'wplnst').'</strong></td><td>'.(empty($link_types)? '' : $link_types.', ').esc_html($scan->destination_type_name).', '.esc_html($scan->time_scope_name).', '.esc_html(__('Order by', 'wplnst')).' '.esc_html($scan->crawl_order_name).', '.($scan->redir_status? __('Check redirection status', 'wplnst') : __('Redirections not checked', 'wplnst')).($scan->malformed? ', '.__('Malformed', 'wplnst') : '').'</td></tr>';
397
-
 
398
  // Post types and status
399
- $item['wplnst-scans-configuration'] .= (empty($scan->post_types_names) && empty($scan->post_status_names))? '' : '<tr><td class="wplnst-scans-configuration-row"><strong>'.__('Post types', 'wplnst').'</strong></td><td>'.(empty($scan->post_types_names)? '' : implode(', ', array_map('esc_html', $scan->post_types_names))).(empty($scan->post_status_names)? '' : (empty($scan->post_types_names)? '' : ', ').__('Post status', 'wplnst').' '.implode(', ', array_map('esc_html', $scan->post_status_names))).'</td></tr>';
400
-
 
401
  // Links status
402
  $item['wplnst-scans-configuration'] .= empty($scan->links_status_names)? '' : '<tr><td class="wplnst-scans-configuration-row"><strong>'.__('Link status', 'wplnst').'</strong></td><td>'.implode(', ', array_map('esc_html', $scan->links_status_names)).'</td></tr>';
403
-
404
  // End configuration
405
  $item['wplnst-scans-configuration'] .= '</table>';
406
-
407
  // Add row
408
  $this->items[] = $item;
409
  }
@@ -420,30 +435,31 @@ class WPLNST_Views_Scans extends WP_List_Table {
420
  * @return mixed
421
  */
422
  protected function column_default($item, $column_name) {
423
-
424
  // Actions for name column
425
  if ('wplnst-scans-name' == $column_name) {
426
-
427
  // Initialize
428
  $actions = array();
429
-
430
  // Results link
431
  $actions['results'] = '<a href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_results($item['ID'])).'">'.__('Show results', 'wplnst').'</a>';
432
-
433
  // Edit link
434
  $actions['edit'] = '<span class="edit"><a href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_edit($item['ID'])).'">'.__('Edit scan', 'wplnst').'</a></span>';
435
-
436
  // Stop or start crawler
437
- if ('end' != $item['status'] && ($item['ready'] || 'play' == $item['status']))
438
  $actions['crawler'] = '<a href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($item['ID'], ('play' == $item['status'] || 'queued' == $item['status'])? 'off' : 'on', $item['hash'])).'">'.(in_array($item['status'], array('wait', 'stop'))? __('Start crawler', 'wplnst') : (('queued' == $item['status'])? __('Unqueue crawling', 'wplnst') : __('Stop crawler', 'wplnst'))).'</a>';
439
-
 
440
  // Remove scan
441
  $actions['delete'] = '<span class="trash"><a href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_delete($item['ID'], $item['hash'])).'" class="wplnst-scan-delete">'.esc_html(WPLNST_Admin::get_text('scan_delete')).'</a></span>';
442
-
443
  // Done
444
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions));
445
  }
446
-
447
  // Default column
448
  return $item[$column_name];
449
  }
@@ -466,7 +482,7 @@ class WPLNST_Views_Scans extends WP_List_Table {
466
 
467
  /**
468
  * Handles the checkbox column output.
469
- */
470
  protected function column_cb($item) {
471
  return $this->results->isolated? null : sprintf('<input type="checkbox" class="wplnst-ck-scan-id" value="%s" />', $item['ID']);
472
  }
@@ -493,19 +509,21 @@ class WPLNST_Views_Scans extends WP_List_Table {
493
  * @access public
494
  */
495
  public function display() {
496
-
497
  // Wrapper form
498
  echo '<form method="get" action="'.esc_url($this->base_url).'" id="wplnst-scans" data-href-delete="'.WPLNST_Core_Plugin::get_url_scans_delete('%scan_id%', 'bulk-scans-delete').'" data-confirm-delete="'.esc_attr(WPLNST_Admin::get_text('scan_delete_confirm')).'" data-confirm-delete-bulk="'.esc_attr__('Do you want to remove these scans?', 'wplnst').'">';
499
-
500
  // Check isolated classes
501
  $extra_classes = array();
502
- if ($this->results->isolated)
503
  $extra_classes[] = 'wplnst-isolated-table';
504
-
 
505
  // Check isolated display
506
- if (!$this->results->isolated)
507
  $this->display_tablenav('top');
508
-
 
509
  ?><table class="wp-list-table <?php echo implode(' ', array_merge($this->get_table_classes(), $extra_classes)); ?>">
510
  <thead>
511
  <tr>
@@ -523,11 +541,12 @@ class WPLNST_Views_Scans extends WP_List_Table {
523
  </tfoot>
524
  <?php endif; ?>
525
  </table><?php
526
-
527
  // Check isolated display
528
- if (!$this->results->isolated)
529
  $this->display_tablenav('bottom');
530
-
 
531
  // Close form
532
  echo '</form>';
533
  }
1
  <?php
2
 
3
  // Check WP constant
4
+ if (!defined('ABSPATH')) {
5
  die;
6
+ }
7
 
8
  // Check dependencies
9
+ if (!class_exists('WP_List_Table')) {
10
+ require_once ABSPATH.'wp-admin/includes/class-wp-list-table.php';
11
+ }
12
 
13
  /**
14
+ * Scans class
15
  *
16
  * @package WP Link Status
17
+ * @subpackage Views
18
  */
19
  class WPLNST_Views_Scans extends WP_List_Table {
20
 
47
  * Constructor
48
  */
49
  public function __construct($results) {
50
+
51
  // Parent constructor
52
  parent::__construct();
53
+
54
  // Copy results
55
  $this->results = $results;
56
+
57
  // Base link for filters
58
  $this->base_url = esc_url(WPLNST_Core_Plugin::get_url_scans());
59
  }
64
  * Prepare columns and data
65
  */
66
  function prepare_items() {
67
+
68
  // Columns
69
  $this->setup_columns();
70
+
71
  // Data items
72
  $this->setup_items();
73
+
74
  // Pagination
75
  $this->setup_pagination();
76
  }
85
  // Initialize
86
  $hidden = array();
87
  $sortable = array();
88
+
89
  // Column headers
90
  $this->_column_headers = array($this->get_columns(), $hidden, $sortable);
91
  }
96
  * Columns array
97
  */
98
  public function get_columns(){
99
+
100
  // Checkbox column
101
  $columns = array();
102
+ if (!$this->results->isolated) {
103
  $columns['cb'] = '<input type="checkbox" />';
104
+ }
105
+
106
  // All columns
107
  return array_merge($columns, array(
108
  'wplnst-scans-name' => __('Scan info', 'wplnst'),
116
  * Setup data items
117
  */
118
  private function setup_items() {
119
+
120
  // Initialize
121
  $this->items = array();
122
+
123
  // Warning image
124
  $warning_img = '<img src="'.plugins_url('assets/images/scan-warning.png', WPLNST_FILE).'" width="16" height="16" border="0" style="margin-right: 5px;" title="'.__('Some critical values of this scan are not completed', 'wplnst').'">';
125
+
126
  // Populate data
127
  foreach ($this->results->rows as $scan) {
128
+
129
  // Initialize
130
  $timeinfo = false;
131
  $linksinfo = '';
132
+
133
  // Normalize identifiers and other data
134
  $item = array('ID' => $scan->id, 'hash' => $scan->hash, 'status' => $scan->status, 'ready' => $scan->ready);
135
+
136
  // Check processed posts
137
  $message = ('play' != $scan->status)? '' : __('Waiting...', 'wplnst');
138
+
139
  // Initialize
140
  $processed = array();
141
  $running_back = false;
142
  $class_completed = ('end' == $scan->status)? 'wplnst-scan-object-completed-end' : 'wplnst-scan-object-completed';
143
+
144
  if (isset($scan->trace['total_posts'])) {
145
  $running_back = empty($scan->trace['populated_posts']);
146
  $posts_index = empty($scan->trace['posts_index'])? 0 : number_format_i18n($scan->trace['posts_index']);
147
  $processed[] = empty($scan->trace['populated_posts'])? '<span class="wplnst-scan-object-info wplnst-scan-object-running">'.$posts_index.'/'.number_format_i18n($scan->trace['total_posts']).' '.__('entries', 'wplnst').'</span>' : '<span class="wplnst-scan-object-info '.$class_completed.'">'.number_format_i18n($scan->trace['total_posts']).' '.__('entries', 'wplnst').'</span>';
148
  }
149
+
150
  if (isset($scan->trace['total_comments'])) {
151
  $running = !$running_back && empty($scan->trace['populated_comments']);
152
  $running_back = $running? true : $running_back;
154
  $comments_index = empty($scan->trace['comments_index'])? 0 : number_format_i18n($scan->trace['comments_index']);
155
  $processed[] = empty($scan->trace['populated_comments'])? '<span class="wplnst-scan-object-info '.$class_running.'">'.$comments_index.'/'.number_format_i18n($scan->trace['total_comments']).' '.__('comments', 'wplnst').'</span>' : '<span class="wplnst-scan-object-info '.$class_completed.'">'.number_format_i18n($scan->trace['total_comments']).' '.__('comments', 'wplnst').'</span>';
156
  }
157
+
158
  if (isset($scan->trace['total_blogroll'])) {
159
  $running = !$running_back && empty($scan->trace['populated_blogroll']);
160
  $class_running = $running? 'wplnst-scan-object-running' : 'wplnst-scan-object-wait';
161
  $blogroll_index = empty($scan->trace['blogroll_index'])? 0 : number_format_i18n($scan->trace['blogroll_index']);
162
  $processed[] = empty($scan->trace['populated_blogroll'])? '<span class="wplnst-scan-object-info '.$class_running.'">'.$blogroll_index.'/'.number_format_i18n($scan->trace['total_blogroll']).' '.__('blogroll', 'wplnst').'</span>' : '<span class="wplnst-scan-object-info '.$class_completed.'">'.number_format_i18n($scan->trace['total_blogroll']).' '.__('blogroll', 'wplnst').'</span>';
163
  }
164
+
165
  // Check info
166
  if (!empty($processed)) {
167
+
168
  // Processed object types
169
  $message = implode('&nbsp;', $processed);
170
+
171
  // Check status
172
  if ('wait' != $scan->status) {
173
+
174
+
175
  /* Time info */
176
+
177
  // Start and local extra time
178
  $time_start = strtotime($scan->row->started_at.' UTC');
179
  $offset_time = get_option('gmt_offset') * HOUR_IN_SECONDS;
180
+
181
  // Current dates
182
  $today_date = gmdate('d/m/Y', time() + $offset_time);
183
  $yesterday_date = gmdate('d/m/Y', time() + $offset_time - 86400);
184
+
185
  // Local date and hour
186
  $start_date = gmdate('d/m/Y', $time_start + $offset_time);
187
  $start_hour = gmdate('H:i', $time_start + $offset_time);
188
+
189
  // Check today
190
  if ($start_date == $today_date) {
191
+
192
  // Today
193
  $started_at = sprintf(__('Today from %s', 'wplnst'), $start_hour);
194
+
195
  // Check yesterday
196
  } elseif ($start_date == $yesterday_date) {
197
+
198
  // Yesterday
199
  $started_at = sprintf(__('Yesterday at %s', 'wplnst'), $start_hour);
200
+
201
  // Other
202
  } else {
203
+
204
  // Date and hour
205
  $started_at = sprintf(__('%s at %s', 'wplnst'), $start_date, $start_hour);
206
  }
207
+
208
  // Start date
209
  $timeinfo = $started_at;
210
+
211
  // Retrieve time stopped
212
  $time_stopped = isset($scan->summary['time_stopped'])? (int) $scan->summary['time_stopped'] : 0;
213
+
214
  // Ended scan
215
  if ('end' == $scan->status) {
216
+
217
  // Finished date
218
  $time_end = $time_end_amount = strtotime($scan->row->finished_at.' UTC');
219
+
220
  // Local date and hour
221
  $end_date = gmdate('d/m/Y', $time_end + $offset_time);
222
  $end_hour = gmdate('H:i', $time_end + $offset_time);
223
+
224
  // Check today
225
  if ($end_date == $today_date) {
226
+
227
  // All today
228
  if ($start_date == $today_date) {
229
+
230
  // Started and finished today
231
  $timeinfo .= ' '.sprintf(__('to %s', 'wplnst'), $end_hour);
232
+
233
  // Date to today
234
  } else {
235
+
236
  // Started another date and finished today
237
  $timeinfo .= ' '.sprintf(__('to today at %s', 'wplnst'), $end_hour);
238
  }
239
+
240
  // Check yesterday
241
  } elseif ($end_date == $yesterday_date) {
242
+
243
  // All yesterday
244
  if ($start_date == $yesterday_date) {
245
+
246
  // Started and finished today
247
  $timeinfo .= ' '.sprintf(__('to %s', 'wplnst'), $end_hour);
248
+
249
  // Date to yesterday
250
  } else {
251
+
252
  // Started another date and finished today
253
  $timeinfo .= ' '.sprintf(__('to yesterday at %s', 'wplnst'), $end_hour);
254
  }
255
+
256
  // Check same day
257
  } elseif ($end_date == $start_date) {
258
+
259
  // Same day
260
  $timeinfo .= ' '.sprintf(__('until %s', 'wplnst'), $end_hour);
261
+
262
  // Before
263
  } else {
264
+
265
  // Different days
266
  $timeinfo .= ' '.sprintf(__('until %s at %s', 'wplnst'), $end_date, $end_hour);
267
  }
268
+
269
  // Time stopped correction
270
+ if (!empty($time_stopped)) {
271
  $time_end_amount -= $time_stopped;
272
+ }
273
+
274
  // Total time
275
  $timeinfo .= ' &#8212; '.human_time_diff($time_start, $time_end_amount);
276
+
277
  // Running
278
  } else {
279
+
280
  // Until now or stopped
281
  $time_end = ('stop' == $scan->status)? strtotime($scan->row->stopped_at.' UTC') : time();
282
+
283
  // Time stopped correction
284
+ if (!empty($time_stopped)) {
285
  $time_end -= $time_stopped;
286
+ }
287
+
288
  // Elapsed time
289
  $timeinfo .= ' &#8212; '.sprintf(__('Running time %s', 'wplnst'), human_time_diff($time_start, $time_end));
290
  }
291
+
292
+
293
  /* Links info */
294
+
295
  // Normalize
296
  $phases = array();
297
  foreach ($scan->summary as $key => $value) {
300
  $phases[$phase[1]] = $value;
301
  }
302
  }
303
+
304
  // Check values
305
  if (!empty($phases)) {
306
+
307
  // Collect data
308
  $items = array();
309
+
310
  // All results
311
  $items[] = (isset($scan->summary['status_total']) && $scan->summary['status_total'] > 0)? sprintf(__('<strong>%s</strong> results', 'wplnst'), number_format_i18n((int) $scan->summary['status_total'])) : __('No results', 'wplnst');
312
+
313
  // Total processed
314
  if (!empty($phases['processed'])) {
315
+
316
  // Add uniques
317
  $items[] = sprintf(__('<strong>%s</strong> unique URLs', 'wplnst'), number_format_i18n((int) $phases['processed']));
318
  }
319
+
320
  // Enqueued URLs
321
+ if ('end' != $scan->status) {
322
  $items[] = sprintf(__('%s enqueued', 'wplnst'), (isset($phases['wait'])? number_format_i18n((int) $phases['wait']) : '0'));
323
+ }
324
+
325
  // Waiting
326
+ if ('play' == $scan->status) {
327
  $items[] = sprintf(__('%s processing', 'wplnst'), (empty($phases['play'])? wplnst_get_nsetting('max_threads', $scan->threads->max) : (int) $phases['play']));
328
+ }
329
+
330
  // End crawler
331
+ if ('end' == $scan->status) {
332
  $items[] = sprintf(__('<strong>%s</strong> Request error', 'wplnst'), (isset($scan->summary['status_level_0'])? (int) number_format_i18n($scan->summary['status_level_0']) : '0'));
333
+ }
334
+
335
  // Join items
336
+ if (!empty($items)) {
337
  $linksinfo = implode('<span class="wplnst-split-char">&middot;</span>', $items);
338
+ }
339
  }
340
  }
341
+
342
  // Only created
343
  } elseif ('wait' == $scan->status || 'queued' == $scan->status || 'stop' == $scan->status) {
344
+
345
  // Created date
346
  $time_created = strtotime($scan->row->created_at.' UTC');
347
  $offset_time = get_option('gmt_offset') * HOUR_IN_SECONDS;
348
+
349
  // Current dates
350
  $today_date = gmdate('d/m/Y', time() + $offset_time);
351
  $yesterday_date = gmdate('d/m/Y', time() + $offset_time - 86400);
352
+
353
  // Local date and hour
354
  $created_date = gmdate('d/m/Y', $time_created + $offset_time);
355
  $created_hour = gmdate('H:i', $time_created + $offset_time);
356
+
357
  // Check today
358
  if ($created_date == $today_date) {
359
+
360
  // Created today
361
  $timeinfo = sprintf(__('Created today at %s', 'wplnst'), $created_hour);
362
+
363
  // Yesterday
364
  } elseif ($created_date == $yesterday_date) {
365
+
366
  // Created yesterday
367
  $timeinfo = sprintf(__('Created yesterday at %s', 'wplnst'), $created_hour);
368
+
369
  // Any date
370
  } else {
371
+
372
  // Created date and hour
373
  $timeinfo = sprintf(__('Created %s at %s', 'wplnst'), $created_date, $created_hour);
374
  }
375
  }
376
+
377
+
378
+
379
  // Item name, possible warning and link to edit
380
  $statuses = WPLNST_Core_Types::get_scan_statuses();
381
  $item['wplnst-scans-name'] = '<strong class="wplnst-scan-name'.($scan->ready? '' : ' wplnst-scan-name-warning').'">'.($scan->ready? '' : $warning_img);
382
+ if ('wait' != $scan->status) {
383
  $item['wplnst-scans-name'] .= '<span class="wplnst-scan-status wplnst-scan-status-'.esc_attr($scan->status).'">'.$statuses[$scan->status].'</span>&nbsp;';
384
+ }
385
  $item['wplnst-scans-name'] .= '<a class="row-title" href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_results($scan->id)).'">'.(empty($scan->name)? __('(no name)', 'wplnst') : esc_html($scan->name)).'</a></strong>';
386
  $item['wplnst-scans-name'] .= '<div class="wplnst-scan-status-line">'.$message.'</div>';
387
+
388
  // Check ready message
389
+ if ('wait' == $scan->status && $scan->ready) {
390
  $item['wplnst-scans-name'] .= '<div class="wplnst-scan-ready-info">'.sprintf(__('Ready to <a href="%s">start the crawler</a>', 'wplnst'), esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($scan->id, 'on', $scan->hash))).'</div>';
391
+ }
392
+
393
  // Check datatime info
394
+ if (!empty($timeinfo)) {
395
  $item['wplnst-scans-name'] .= '<div class="wplnst-scan-time-info">'.$timeinfo.'</div>';
396
+ }
397
+
398
  // Check links info
399
+ if (!empty($linksinfo)) {
400
+ $item['wplnst-scans-name'] .= '<div class="wplnst-scan-links-info">'.$linksinfo.'</div>';
401
+ }
402
+
403
+
404
  // Prepare configuration
405
  $item['wplnst-scans-configuration'] = '<table>';
406
+
407
  // Scan scope
408
  $link_types = (empty($scan->link_types_names)? '' : implode(', ', array_map('esc_html', $scan->link_types_names)));
409
+ $item['wplnst-scans-configuration'] .= '<tr><td class="wplnst-scans-configuration-row"><strong>'.__('Scope', 'wplnst').'</strong></td><td>'.
410
+ (empty($link_types)? '' : $link_types.', ').esc_html($scan->destination_type_name).', '.esc_html($scan->time_scope_name).', '.esc_html(__('Order by', 'wplnst')).' '.esc_html($scan->crawl_order_name).', '.($scan->redir_status? __('Check redirection status', 'wplnst') : __('Redirections not checked', 'wplnst')).($scan->malformed? ', '.__('Malformed', 'wplnst') : '').'</td></tr>';
411
+
412
  // Post types and status
413
+ $item['wplnst-scans-configuration'] .= (empty($scan->post_types_names) && empty($scan->post_status_names))? '' :
414
+ '<tr><td class="wplnst-scans-configuration-row"><strong>'.__('Post types', 'wplnst').'</strong></td><td>'.(empty($scan->post_types_names)? '' : implode(', ', array_map('esc_html', $scan->post_types_names))).(empty($scan->post_status_names)? '' : (empty($scan->post_types_names)? '' : ', ').__('Post status', 'wplnst').' '.implode(', ', array_map('esc_html', $scan->post_status_names))).'</td></tr>';
415
+
416
  // Links status
417
  $item['wplnst-scans-configuration'] .= empty($scan->links_status_names)? '' : '<tr><td class="wplnst-scans-configuration-row"><strong>'.__('Link status', 'wplnst').'</strong></td><td>'.implode(', ', array_map('esc_html', $scan->links_status_names)).'</td></tr>';
418
+
419
  // End configuration
420
  $item['wplnst-scans-configuration'] .= '</table>';
421
+
422
  // Add row
423
  $this->items[] = $item;
424
  }
435
  * @return mixed
436
  */
437
  protected function column_default($item, $column_name) {
438
+
439
  // Actions for name column
440
  if ('wplnst-scans-name' == $column_name) {
441
+
442
  // Initialize
443
  $actions = array();
444
+
445
  // Results link
446
  $actions['results'] = '<a href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_results($item['ID'])).'">'.__('Show results', 'wplnst').'</a>';
447
+
448
  // Edit link
449
  $actions['edit'] = '<span class="edit"><a href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_edit($item['ID'])).'">'.__('Edit scan', 'wplnst').'</a></span>';
450
+
451
  // Stop or start crawler
452
+ if ('end' != $item['status'] && ($item['ready'] || 'play' == $item['status'])) {
453
  $actions['crawler'] = '<a href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_crawler($item['ID'], ('play' == $item['status'] || 'queued' == $item['status'])? 'off' : 'on', $item['hash'])).'">'.(in_array($item['status'], array('wait', 'stop'))? __('Start crawler', 'wplnst') : (('queued' == $item['status'])? __('Unqueue crawling', 'wplnst') : __('Stop crawler', 'wplnst'))).'</a>';
454
+ }
455
+
456
  // Remove scan
457
  $actions['delete'] = '<span class="trash"><a href="'.esc_url(WPLNST_Core_Plugin::get_url_scans_delete($item['ID'], $item['hash'])).'" class="wplnst-scan-delete">'.esc_html(WPLNST_Admin::get_text('scan_delete')).'</a></span>';
458
+
459
  // Done
460
  return sprintf('%1$s %2$s', $item[$column_name], $this->row_actions($actions));
461
  }
462
+
463
  // Default column
464
  return $item[$column_name];
465
  }
482
 
483
  /**
484
  * Handles the checkbox column output.
485
+ */
486
  protected function column_cb($item) {
487
  return $this->results->isolated? null : sprintf('<input type="checkbox" class="wplnst-ck-scan-id" value="%s" />', $item['ID']);
488
  }
509
  * @access public
510
  */
511
  public function display() {
512
+
513
  // Wrapper form
514
  echo '<form method="get" action="'.esc_url($this->base_url).'" id="wplnst-scans" data-href-delete="'.WPLNST_Core_Plugin::get_url_scans_delete('%scan_id%', 'bulk-scans-delete').'" data-confirm-delete="'.esc_attr(WPLNST_Admin::get_text('scan_delete_confirm')).'" data-confirm-delete-bulk="'.esc_attr__('Do you want to remove these scans?', 'wplnst').'">';
515
+
516
  // Check isolated classes
517
  $extra_classes = array();
518
+ if ($this->results->isolated) {
519
  $extra_classes[] = 'wplnst-isolated-table';
520
+ }
521
+
522
  // Check isolated display
523
+ if (!$this->results->isolated) {
524
  $this->display_tablenav('top');
525
+ }
526
+
527
  ?><table class="wp-list-table <?php echo implode(' ', array_merge($this->get_table_classes(), $extra_classes)); ?>">
528
  <thead>
529
  <tr>
541
  </tfoot>
542
  <?php endif; ?>
543
  </table><?php
544
+
545
  // Check isolated display
546
+ if (!$this->results->isolated) {
547
  $this->display_tablenav('bottom');
548
+ }
549
+
550
  // Close form
551
  echo '</form>';
552
  }
views/settings.php CHANGED
@@ -1,13 +1,13 @@
1
  <?php
2
 
3
  // Load views class
4
- require_once(dirname(__FILE__).'/views.php');
5
 
6
  /**
7
- * WP Link Status Views Settings class
8
  *
9
  * @package WP Link Status
10
- * @subpackage WP Link Status Views
11
  */
12
  class WPLNST_Views_Settings extends WPLNST_Views {
13
 
@@ -17,24 +17,24 @@ class WPLNST_Views_Settings extends WPLNST_Views {
17
  * Show scan edit form
18
  */
19
  public static function view($args) {
20
-
21
  // Vars
22
  extract($args);
23
-
24
  ?><form method="post" id="wplnst-form" action="<?php echo esc_url($action); ?>">
25
-
26
  <input type="hidden" name="settings_nonce" value="<?php echo esc_attr($nonce); ?>" />
27
-
28
  <h2 id="wplnst-tabs-nav" class="nav-tab-wrapper">
29
  <a id="wplnst-crawling-tab" href="#top#wplnst-crawling" class="nav-tab"><?php _e('Crawling', 'wplnst'); ?></a>
30
  <a id="wplnst-timing-tab" href="#top#wplnst-timing" class="nav-tab"><?php _e('Timing', 'wplnst'); ?></a>
31
  <a id="wplnst-advanced-tab" href="#top#wplnst-advanced" class="nav-tab"><?php _e('Advanced', 'wplnst'); ?></a>
32
  </h2>
33
-
34
  <div id="wplnst-tabs">
35
-
36
  <div id="wplnst-crawling" class="wplnst-tab wplnst-tab-default">
37
-
38
  <table class="form-table">
39
  <tr>
40
  <th><label for="tx-max-threads"><?php _e('Number of crawler threads', 'wplnst'); ?></label></th>
@@ -71,11 +71,11 @@ class WPLNST_Views_Settings extends WPLNST_Views {
71
  <td colspan="3" class="wplnst-col-input"><input type="text" name="tx-user-agent" id="tx-user-agent" value="<?php echo esc_attr(wplnst_get_tsetting('user_agent')); ?>" maxlength="255" class="regular-text" style="width: 75%;" /></td>
72
  </tr>
73
  </table>
74
-
75
  </div>
76
-
77
  <div id="wplnst-timing" class="wplnst-tab">
78
-
79
  <table class="form-table">
80
  <tr>
81
  <th><label for="tx-connect-timeout"><?php _e('URL Connection timeout', 'wplnst'); ?></label></th>
@@ -118,12 +118,12 @@ class WPLNST_Views_Settings extends WPLNST_Views {
118
  <td class="wplnst-col-info"><?php _e('seconds', 'wplnst'); ?> <?php printf(__('(mininum value of %d seconds)', 'wplnst'), wplnst_get_nsetting('summary_objects', 'min')); ?>. <?php _e('Summary of objects (posts, comments or blogroll) with processed URLs.', 'wplnst'); ?></td>
119
  </tr>
120
  </table>
121
-
122
  </div>
123
-
124
-
125
  <div id="wplnst-advanced" class="wplnst-tab">
126
-
127
  <table class="form-table">
128
  <tr>
129
  <th><label for="tx-recursion-limit"><?php _e('Recursion limit', 'wplnst'); ?></label></th>
@@ -138,14 +138,14 @@ class WPLNST_Views_Settings extends WPLNST_Views {
138
  <td colspan="2" class="wplnst-list"><input type="checkbox" <?php echo wplnst_get_bsetting('uninstall_data')? 'checked' : ''; ?> name="ck-uninstall-data" id="ck-uninstall-data" value="on" /><label for="ck-uninstall-data">&nbsp;<?php _e('Options and exclusive MySQL tables will be removed when uninstall this plugin.', 'wplnst'); ?></label></td>
139
  </tr>
140
  </table>
141
-
142
  </div>
143
-
144
-
145
  <p><input type="submit" value="<?php _e('Save settings', 'wplnst'); ?>" class="button button-primary" /></p>
146
-
147
  </div>
148
-
149
  </form><?php
150
  }
151
 
1
  <?php
2
 
3
  // Load views class
4
+ require_once dirname(__FILE__).'/views.php';
5
 
6
  /**
7
+ * Settings class
8
  *
9
  * @package WP Link Status
10
+ * @subpackage Views
11
  */
12
  class WPLNST_Views_Settings extends WPLNST_Views {
13
 
17
  * Show scan edit form
18
  */
19
  public static function view($args) {
20
+
21
  // Vars
22
  extract($args);
23
+
24
  ?><form method="post" id="wplnst-form" action="<?php echo esc_url($action); ?>">
25
+
26
  <input type="hidden" name="settings_nonce" value="<?php echo esc_attr($nonce); ?>" />
27
+
28
  <h2 id="wplnst-tabs-nav" class="nav-tab-wrapper">
29
  <a id="wplnst-crawling-tab" href="#top#wplnst-crawling" class="nav-tab"><?php _e('Crawling', 'wplnst'); ?></a>
30
  <a id="wplnst-timing-tab" href="#top#wplnst-timing" class="nav-tab"><?php _e('Timing', 'wplnst'); ?></a>
31
  <a id="wplnst-advanced-tab" href="#top#wplnst-advanced" class="nav-tab"><?php _e('Advanced', 'wplnst'); ?></a>
32
  </h2>
33
+
34
  <div id="wplnst-tabs">
35
+
36
  <div id="wplnst-crawling" class="wplnst-tab wplnst-tab-default">
37
+
38
  <table class="form-table">
39
  <tr>
40
  <th><label for="tx-max-threads"><?php _e('Number of crawler threads', 'wplnst'); ?></label></th>
71
  <td colspan="3" class="wplnst-col-input"><input type="text" name="tx-user-agent" id="tx-user-agent" value="<?php echo esc_attr(wplnst_get_tsetting('user_agent')); ?>" maxlength="255" class="regular-text" style="width: 75%;" /></td>
72
  </tr>
73
  </table>
74
+
75
  </div>
76
+
77
  <div id="wplnst-timing" class="wplnst-tab">
78
+
79
  <table class="form-table">
80
  <tr>
81
  <th><label for="tx-connect-timeout"><?php _e('URL Connection timeout', 'wplnst'); ?></label></th>
118
  <td class="wplnst-col-info"><?php _e('seconds', 'wplnst'); ?> <?php printf(__('(mininum value of %d seconds)', 'wplnst'), wplnst_get_nsetting('summary_objects', 'min')); ?>. <?php _e('Summary of objects (posts, comments or blogroll) with processed URLs.', 'wplnst'); ?></td>
119
  </tr>
120
  </table>
121
+
122
  </div>
123
+
124
+
125
  <div id="wplnst-advanced" class="wplnst-tab">
126
+
127
  <table class="form-table">
128
  <tr>
129
  <th><label for="tx-recursion-limit"><?php _e('Recursion limit', 'wplnst'); ?></label></th>
138
  <td colspan="2" class="wplnst-list"><input type="checkbox" <?php echo wplnst_get_bsetting('uninstall_data')? 'checked' : ''; ?> name="ck-uninstall-data" id="ck-uninstall-data" value="on" /><label for="ck-uninstall-data">&nbsp;<?php _e('Options and exclusive MySQL tables will be removed when uninstall this plugin.', 'wplnst'); ?></label></td>
139
  </tr>
140
  </table>
141
+
142
  </div>
143
+
144
+
145
  <p><input type="submit" value="<?php _e('Save settings', 'wplnst'); ?>" class="button button-primary" /></p>
146
+
147
  </div>
148
+
149
  </form><?php
150
  }
151
 
views/views.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
  /**
4
- * WP Link Status Views class
5
  *
6
  * @package WP Link Status
7
- * @subpackage WP Link Status Views
8
  */
9
  abstract class WPLNST_Views {
10
 
@@ -14,11 +14,21 @@ abstract class WPLNST_Views {
14
  * Compose select option values
15
  */
16
  public static function options($options, $values, $display = true, $space = false) {
 
 
17
  $inner = '';
18
- foreach ($options as $key => $name)
 
 
19
  $inner .= '<option'.(self::selected($key, $values, false)? ' selected' : '').' value="'.esc_attr($key).'">'.esc_html($name).'</option>';
20
- if ($display)
 
 
 
21
  echo $inner;
 
 
 
22
  return $inner;
23
  }
24
 
@@ -29,8 +39,9 @@ abstract class WPLNST_Views {
29
  */
30
  public static function checked($current, $values, $display = true) {
31
  $checked = self::is_value($current, $values);
32
- if ($checked && $display)
33
  echo 'checked';
 
34
  return $checked;
35
  }
36
 
@@ -41,8 +52,9 @@ abstract class WPLNST_Views {
41
  */
42
  public static function selected($current, $values, $display = true, $space = false) {
43
  $selected = self::is_value($current, $values);
44
- if ($selected && $display)
45
  echo ($space? ' ' : '').'selected';
 
46
  return $selected;
47
  }
48
 
@@ -52,8 +64,9 @@ abstract class WPLNST_Views {
52
  * Check if value match an array of values
53
  */
54
  public static function is_value($current, $values) {
55
- if (empty($values) && false !== $values)
56
  return false;
 
57
  return is_array($values)? in_array($current, $values) : ($current == $values);
58
  }
59
 
@@ -66,8 +79,9 @@ abstract class WPLNST_Views {
66
  $json_new = array();
67
  foreach ($json as $json_item) {
68
  $json_item_new = array();
69
- foreach ($json_item as $key => $value)
70
  $json_item_new[esc_attr($key)] = esc_attr($value);
 
71
  $json_new[] = $json_item_new;
72
  }
73
  return str_replace('&quot;', '%quot%', @json_encode($json_new));
1
  <?php
2
 
3
  /**
4
+ * Views class
5
  *
6
  * @package WP Link Status
7
+ * @subpackage Views
8
  */
9
  abstract class WPLNST_Views {
10
 
14
  * Compose select option values
15
  */
16
  public static function options($options, $values, $display = true, $space = false) {
17
+
18
+ // Init
19
  $inner = '';
20
+
21
+ // Compose options
22
+ foreach ($options as $key => $name) {
23
  $inner .= '<option'.(self::selected($key, $values, false)? ' selected' : '').' value="'.esc_attr($key).'">'.esc_html($name).'</option>';
24
+ }
25
+
26
+ // Check display
27
+ if ($display) {
28
  echo $inner;
29
+ }
30
+
31
+ // Done
32
  return $inner;
33
  }
34
 
39
  */
40
  public static function checked($current, $values, $display = true) {
41
  $checked = self::is_value($current, $values);
42
+ if ($checked && $display) {
43
  echo 'checked';
44
+ }
45
  return $checked;
46
  }
47
 
52
  */
53
  public static function selected($current, $values, $display = true, $space = false) {
54
  $selected = self::is_value($current, $values);
55
+ if ($selected && $display) {
56
  echo ($space? ' ' : '').'selected';
57
+ }
58
  return $selected;
59
  }
60
 
64
  * Check if value match an array of values
65
  */
66
  public static function is_value($current, $values) {
67
+ if (empty($values) && false !== $values) {
68
  return false;
69
+ }
70
  return is_array($values)? in_array($current, $values) : ($current == $values);
71
  }
72
 
79
  $json_new = array();
80
  foreach ($json as $json_item) {
81
  $json_item_new = array();
82
+ foreach ($json_item as $key => $value) {
83
  $json_item_new[esc_attr($key)] = esc_attr($value);
84
+ }
85
  $json_new[] = $json_item_new;
86
  }
87
  return str_replace('&quot;', '%quot%', @json_encode($json_new));
wp-link-status.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: WP Broken Link Status Checker
4
  Plugin URI: http://seedplugins.com/wp-link-status/
5
  Description: Check and manage HTTP response codes of all your content site links and images.
6
- Version: 1.0.4
7
  Author: Pau Iglesias, SeedPlugins
8
  License: GPLv2 or later
9
  Text Domain: wplnst
@@ -11,46 +11,53 @@ Domain Path: /languages
11
  */
12
 
13
  // Avoid script calls via plugin URL
14
- if (!function_exists('add_action'))
15
  die;
 
16
 
17
  // Boot checks
18
- require(dirname(__FILE__).'/core/boot.php');
19
 
20
  // This plugin constants
21
  define('WPLNST_FILE', __FILE__);
22
  define('WPLNST_PATH', dirname(WPLNST_FILE));
23
- define('WPLNST_VERSION', '1.0.4');
24
 
25
  // Check scan crawling action
26
- require_once(WPLNST_PATH.'/core/alive.php');
27
  WPLNST_Core_Alive::check();
28
 
29
- // Check context
30
  if (is_admin()) {
31
-
32
- // Admin area
33
  wplnst_require('admin', 'admin');
34
  WPLNST_Admin::instantiate();
35
-
36
- // Plugin activation
37
- register_activation_hook(WPLNST_FILE, 'wplnst_plugin_activation');
38
- function wplnst_plugin_activation() {
39
- wplnst_require('core', 'register');
40
- WPLNST_Core_Register::activation();
41
- }
42
-
43
- // Plugin deactivation
44
- register_deactivation_hook(WPLNST_FILE, 'wplnst_plugin_deactivation');
45
- function wplnst_plugin_deactivation() {
46
- wplnst_require('core', 'register');
47
- WPLNST_Core_Register::deactivation();
48
- }
49
-
50
- // Plugin uninstall
51
- register_uninstall_hook(WPLNST_FILE, 'wplnst_plugin_uninstall');
52
- function wplnst_plugin_uninstall() {
53
- wplnst_require('core', 'register');
54
- WPLNST_Core_Register::uninstall();
55
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  }
3
  Plugin Name: WP Broken Link Status Checker
4
  Plugin URI: http://seedplugins.com/wp-link-status/
5
  Description: Check and manage HTTP response codes of all your content site links and images.
6
+ Version: 1.0.5
7
  Author: Pau Iglesias, SeedPlugins
8
  License: GPLv2 or later
9
  Text Domain: wplnst
11
  */
12
 
13
  // Avoid script calls via plugin URL
14
+ if (!function_exists('add_action')) {
15
  die;
16
+ }
17
 
18
  // Boot checks
19
+ require dirname(__FILE__).'/core/boot.php';
20
 
21
  // This plugin constants
22
  define('WPLNST_FILE', __FILE__);
23
  define('WPLNST_PATH', dirname(WPLNST_FILE));
24
+ define('WPLNST_VERSION', '1.0.5');
25
 
26
  // Check scan crawling action
27
+ require_once WPLNST_PATH.'/core/alive.php';
28
  WPLNST_Core_Alive::check();
29
 
30
+ // Check admin area
31
  if (is_admin()) {
 
 
32
  wplnst_require('admin', 'admin');
33
  WPLNST_Admin::instantiate();
34
+ }
35
+
36
+ // Plugin activation
37
+ register_activation_hook(WPLNST_FILE, 'wplnst_plugin_activation');
38
+ function wplnst_plugin_activation($networkwide = false) {
39
+
40
+ // Prevent network-wide activation
41
+ if (is_multisite() && $networkwide) {
42
+ deactivate_plugins(plugin_basename(WPLNST_FILE));
43
+ wp_die('<p><strong>WP Link Status</strong> cannot be activated network-wide.</p><p>Please activate it invididually per each site where you need it.</p><p>Sorry for the inconvenience.</p>');
 
 
 
 
 
 
 
 
 
 
44
  }
45
+
46
+ // Continues activation
47
+ wplnst_require('core', 'register');
48
+ WPLNST_Core_Register::activation();
49
+ }
50
+
51
+ // Plugin deactivation
52
+ register_deactivation_hook(WPLNST_FILE, 'wplnst_plugin_deactivation');
53
+ function wplnst_plugin_deactivation() {
54
+ wplnst_require('core', 'register');
55
+ WPLNST_Core_Register::deactivation();
56
+ }
57
+
58
+ // Plugin uninstall
59
+ register_uninstall_hook(WPLNST_FILE, 'wplnst_plugin_uninstall');
60
+ function wplnst_plugin_uninstall() {
61
+ wplnst_require('core', 'register');
62
+ WPLNST_Core_Register::uninstall();
63
  }