Version Description
Current Release = Released: 22nd May, 2018 - Release Notes
(v.1) ADDED: [PRO] Admin Notes feature - you can add notes to the Shield plugin in the Insights Dashboard.
(v.1) FIXED: A few bugs with the Insights Dashboard.
(v.0) ADDED: A simple test cron to demonstrate whether your site crons are running.
(v.0) ADDED: [PRO] Full support for new WordPress GDPR Privacy Policy controls for exporting and erasing data.
(v.0) ADDED: [PRO] New GDPR guided wizard for exporting/erasing particular data based on custom search results.
(v.0) CHANGED: Guided Wizards now load through WP admin to fix ajax problems for poorly configured SSL on some sites
(v.0) IMPROVED: Upgraded Bootstrap library to 4.1.1.
(v.0) IMPROVED: Compatibility with AIO Events Cal - they like to force their old Twig libraries on everyone else.
Note: The Insights Dashboard is only available on sites with PHP v5.4.0 and above.
Release Info
Developer | paultgoodchild |
Plugin | Shield Security for WordPress |
Version | 6.7.1 |
Comparing to | |
See all releases |
Code changes from version 6.7.0 to 6.7.1
- icwp-wpsf.php +1 -1
- plugin-spec.php +2 -2
- readme.txt +7 -5
- resources/js/plugin.js +74 -1
- src/common/icwp-wpfunctions.php +1 -1
- src/config/feature-plugin.php +8 -0
- src/features/admin_access_restriction.php +32 -0
- src/features/base.php +9 -0
- src/features/hack_protect.php +100 -0
- src/features/insights.php +161 -275
- src/features/lockdown.php +28 -0
- src/features/plugin.php +20 -0
- src/features/user_management.php +44 -1
- src/processors/basedb.php +7 -0
- src/processors/plugin.php +13 -0
- src/processors/plugin_notes.php +87 -0
- src/processors/sessions.php +2 -2
- src/query/ICWP_WPSF_NoteVO.php +67 -0
- src/query/base.php +49 -0
- src/query/base_find.php +6 -43
- src/query/plugin_notes_create.php +27 -0
- src/query/plugin_notes_delete.php +19 -0
- src/query/plugin_notes_find.php +82 -0
- src/query/plugin_notes_retrieve.php +65 -0
- templates/twig/wpadmin_pages/insights/admin_notes.twig +34 -0
- templates/twig/wpadmin_pages/insights/admin_notes_table.twig +18 -0
- templates/twig/wpadmin_pages/insights/index.twig +15 -7
- templates/twig/wpadmin_pages/insights/stats.twig +1 -1
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Shield Security
|
4 |
* Plugin URI: http://icwp.io/2f
|
5 |
* Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
|
6 |
-
* Version: 6.7.
|
7 |
* Text Domain: wp-simple-firewall
|
8 |
* Domain Path: /languages/
|
9 |
* Author: One Dollar Plugin
|
3 |
* Plugin Name: Shield Security
|
4 |
* Plugin URI: http://icwp.io/2f
|
5 |
* Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
|
6 |
+
* Version: 6.7.1
|
7 |
* Text Domain: wp-simple-firewall
|
8 |
* Domain Path: /languages/
|
9 |
* Author: One Dollar Plugin
|
@@ -1,7 +1,7 @@
|
|
1 |
{
|
2 |
"properties": {
|
3 |
-
"version": "6.7.
|
4 |
-
"release_timestamp":
|
5 |
"slug_parent": "icwp",
|
6 |
"slug_plugin": "wpsf",
|
7 |
"human_name": "Shield",
|
1 |
{
|
2 |
"properties": {
|
3 |
+
"version": "6.7.1",
|
4 |
+
"release_timestamp": 1526972443,
|
5 |
"slug_parent": "icwp",
|
6 |
"slug_plugin": "wpsf",
|
7 |
"human_name": "Shield",
|
@@ -8,7 +8,7 @@ Requires at least: 3.5.0
|
|
8 |
Requires PHP: 5.2.4
|
9 |
Recommended PHP: 5.4
|
10 |
Tested up to: 4.9
|
11 |
-
Stable tag: 6.7.
|
12 |
|
13 |
Complete All-In-One Protection for your WordPress sites, that makes Security Easy for Everyone - it doesn't have to be hard anymore.
|
14 |
|
@@ -353,11 +353,11 @@ If you don't want to support the work, no problem! You can still continue to use
|
|
353 |
|
354 |
You can [go Pro for just $1/month](http://icwp.io/aa).
|
355 |
|
356 |
-
= 6.7.
|
357 |
-
*Released:
|
358 |
|
359 |
-
* **(v.
|
360 |
-
* **(v.
|
361 |
* **(v.0)** ADDED: A simple test cron to demonstrate whether your site crons are running.
|
362 |
* **(v.0)** ADDED: [**PRO**] Full support for new WordPress GDPR Privacy Policy controls for exporting and erasing data.
|
363 |
* **(v.0)** ADDED: [**PRO**] New GDPR guided wizard for exporting/erasing particular data based on custom search results.
|
@@ -370,6 +370,8 @@ Note: The Insights Dashboard is only available on sites with PHP v5.4.0 and abov
|
|
370 |
= 6.7 Series =
|
371 |
*Released: 21st May, 2018* - [Release Notes](http://icwp.io/cx)
|
372 |
|
|
|
|
|
373 |
* **(v.0)** ADDED: All-New Insights Dashboard providing a high-level overview of your site security, with recommendations.
|
374 |
* **(v.0)** ADDED: Helpful, explanatory videos directly into the Guided Welcome Wizard.
|
375 |
* **(v.0)** ADDED: A simple test cron to demonstrate whether your site crons are running.
|
8 |
Requires PHP: 5.2.4
|
9 |
Recommended PHP: 5.4
|
10 |
Tested up to: 4.9
|
11 |
+
Stable tag: 6.7.1
|
12 |
|
13 |
Complete All-In-One Protection for your WordPress sites, that makes Security Easy for Everyone - it doesn't have to be hard anymore.
|
14 |
|
353 |
|
354 |
You can [go Pro for just $1/month](http://icwp.io/aa).
|
355 |
|
356 |
+
= 6.7.1 - Current Release =
|
357 |
+
*Released: 22nd May, 2018* - [Release Notes](http://icwp.io/cx)
|
358 |
|
359 |
+
* **(v.1)** ADDED: [**PRO**] Admin Notes feature - you can add notes to the Shield plugin in the Insights Dashboard.
|
360 |
+
* **(v.1)** FIXED: A few bugs with the Insights Dashboard.
|
361 |
* **(v.0)** ADDED: A simple test cron to demonstrate whether your site crons are running.
|
362 |
* **(v.0)** ADDED: [**PRO**] Full support for new WordPress GDPR Privacy Policy controls for exporting and erasing data.
|
363 |
* **(v.0)** ADDED: [**PRO**] New GDPR guided wizard for exporting/erasing particular data based on custom search results.
|
370 |
= 6.7 Series =
|
371 |
*Released: 21st May, 2018* - [Release Notes](http://icwp.io/cx)
|
372 |
|
373 |
+
* **(v.1)** FIXED: A few bugs with the Insights Dashboard
|
374 |
+
* **(v.1)** ADDED: [**PRO**] Admin Notes feature - you can now add notes to the Shield plugin in the Insights Dashboard.
|
375 |
* **(v.0)** ADDED: All-New Insights Dashboard providing a high-level overview of your site security, with recommendations.
|
376 |
* **(v.0)** ADDED: Helpful, explanatory videos directly into the Guided Welcome Wizard.
|
377 |
* **(v.0)** ADDED: A simple test cron to demonstrate whether your site crons are running.
|
@@ -88,5 +88,78 @@ var iCWP_WPSF_OptionsFormSubmit = new function () {
|
|
88 |
};
|
89 |
}();
|
90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
iCWP_WPSF_OptionsPages.initialise();
|
92 |
-
iCWP_WPSF_OptionsFormSubmit.initialise();
|
|
88 |
};
|
89 |
}();
|
90 |
|
91 |
+
var iCWP_WPSF_InsightsAdminNotes = new function () {
|
92 |
+
|
93 |
+
var bRequestCurrentlyRunning = false;
|
94 |
+
|
95 |
+
/**
|
96 |
+
*/
|
97 |
+
var renderNotes = function ( event ) {
|
98 |
+
|
99 |
+
jQuery.post( ajaxurl, icwp_wpsf_vars_insights.ajax_admin_notes_render,
|
100 |
+
function ( oResponse ) {
|
101 |
+
if ( oResponse.success ) {
|
102 |
+
jQuery( '#AdminNotesContainer' ).html( oResponse.data.html );
|
103 |
+
}
|
104 |
+
else {
|
105 |
+
var sMessage = 'Communications error with site.';
|
106 |
+
if ( oResponse.data.message !== undefined ) {
|
107 |
+
sMessage = oResponse.data.message;
|
108 |
+
}
|
109 |
+
alert( sMessage );
|
110 |
+
}
|
111 |
+
}
|
112 |
+
).always( function () {
|
113 |
+
iCWP_WPSF_BodyOverlay.hide();
|
114 |
+
}
|
115 |
+
);
|
116 |
+
};
|
117 |
+
|
118 |
+
/**
|
119 |
+
*/
|
120 |
+
var submitForm = function ( event ) {
|
121 |
+
iCWP_WPSF_BodyOverlay.show();
|
122 |
+
|
123 |
+
if ( bRequestCurrentlyRunning ) {
|
124 |
+
return false;
|
125 |
+
}
|
126 |
+
bRequestCurrentlyRunning = true;
|
127 |
+
event.preventDefault();
|
128 |
+
|
129 |
+
jQuery.post( ajaxurl, jQuery( this ).serialize(),
|
130 |
+
function ( oResponse ) {
|
131 |
+
if ( oResponse.success ) {
|
132 |
+
renderNotes(); // this will remove the overlay
|
133 |
+
}
|
134 |
+
else {
|
135 |
+
var sMessage = 'Communications error with site.';
|
136 |
+
if ( oResponse.data.message !== undefined ) {
|
137 |
+
sMessage = oResponse.data.message;
|
138 |
+
}
|
139 |
+
alert( sMessage );
|
140 |
+
iCWP_WPSF_BodyOverlay.hide();
|
141 |
+
}
|
142 |
+
}
|
143 |
+
).always( function () {
|
144 |
+
bRequestCurrentlyRunning = false;
|
145 |
+
}
|
146 |
+
);
|
147 |
+
};
|
148 |
+
|
149 |
+
this.initialise = function () {
|
150 |
+
jQuery( document ).ready( function () {
|
151 |
+
jQuery( document ).on( "keydown", "form#NewAdminNote", function ( e ) {
|
152 |
+
/* if ( e.ctrlKey && e.keyCode === 13 ) {
|
153 |
+
can't get ctrl+return to submit!
|
154 |
+
console.log( e );
|
155 |
+
submitForm( e );
|
156 |
+
} */
|
157 |
+
} );
|
158 |
+
jQuery( document ).on( "submit", "form#NewAdminNote", submitForm );
|
159 |
+
} );
|
160 |
+
};
|
161 |
+
}();
|
162 |
+
|
163 |
iCWP_WPSF_OptionsPages.initialise();
|
164 |
+
iCWP_WPSF_OptionsFormSubmit.initialise();
|
165 |
+
iCWP_WPSF_InsightsAdminNotes.initialise();
|
@@ -404,7 +404,7 @@ class ICWP_WPSF_WpFunctions extends ICWP_WPSF_Foundation {
|
|
404 |
*/
|
405 |
public function hasCoreUpdate() {
|
406 |
$aUpdates = $this->getCoreUpdates();
|
407 |
-
return (
|
408 |
}
|
409 |
|
410 |
public function redirectHere() {
|
404 |
*/
|
405 |
public function hasCoreUpdate() {
|
406 |
$aUpdates = $this->getCoreUpdates();
|
407 |
+
return ( isset( $aUpdates[ 0 ]->response ) && 'latest' != $aUpdates[ 0 ]->response );
|
408 |
}
|
409 |
|
410 |
public function redirectHere() {
|
@@ -399,6 +399,14 @@
|
|
399 |
"tracking_post_url": "https://tracking.icontrolwp.com/track/plugin/shield",
|
400 |
"importexport_cron_name": "autoimport",
|
401 |
"href_privacy_policy": "http://icwp.io/wpshieldprivacypolicy",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
402 |
"active_plugin_features": [
|
403 |
{
|
404 |
"slug": "insights",
|
399 |
"tracking_post_url": "https://tracking.icontrolwp.com/track/plugin/shield",
|
400 |
"importexport_cron_name": "autoimport",
|
401 |
"href_privacy_policy": "http://icwp.io/wpshieldprivacypolicy",
|
402 |
+
"db_notes_name": "notes",
|
403 |
+
"db_notes_table_columns": [
|
404 |
+
"id",
|
405 |
+
"wp_username",
|
406 |
+
"note",
|
407 |
+
"created_at",
|
408 |
+
"deleted_at"
|
409 |
+
],
|
410 |
"active_plugin_features": [
|
411 |
{
|
412 |
"slug": "insights",
|
@@ -361,6 +361,38 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
361 |
return $this;
|
362 |
}
|
363 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
364 |
/**
|
365 |
* @param array $aOptionsParams
|
366 |
* @return array
|
361 |
return $this;
|
362 |
}
|
363 |
|
364 |
+
/**
|
365 |
+
* @param array $aAllNotices
|
366 |
+
* @return array
|
367 |
+
*/
|
368 |
+
public function addInsightsNoticeData( $aAllNotices ) {
|
369 |
+
|
370 |
+
$aNotices = array(
|
371 |
+
'title' => _wpsf__( 'Security Admin Protection' ),
|
372 |
+
'messages' => array()
|
373 |
+
);
|
374 |
+
|
375 |
+
{//sec admin
|
376 |
+
if ( !( $this->isModuleEnabled() && $this->hasAccessKey() ) ) {
|
377 |
+
$aNotices[ 'messages' ][ 'sec_admin' ] = array(
|
378 |
+
'title' => 'Security Plugin Unprotected',
|
379 |
+
'message' => sprintf(
|
380 |
+
_wpsf__( "The Security Admin protection is not active." ),
|
381 |
+
$this->getConn()->getHumanName()
|
382 |
+
),
|
383 |
+
'href' => $this->getUrl_AdminPage(),
|
384 |
+
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
385 |
+
'rec' => _wpsf__( 'Security Admin should be turned-on to protect your security settings.' )
|
386 |
+
);
|
387 |
+
}
|
388 |
+
}
|
389 |
+
|
390 |
+
$aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
|
391 |
+
$aAllNotices[ 'sec_admin' ] = $aNotices;
|
392 |
+
|
393 |
+
return $aAllNotices;
|
394 |
+
}
|
395 |
+
|
396 |
/**
|
397 |
* @param array $aOptionsParams
|
398 |
* @return array
|
@@ -120,6 +120,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
120 |
$nMenuPriority = isset( $aModProps[ 'menu_priority' ] ) ? $aModProps[ 'menu_priority' ] : 100;
|
121 |
add_filter( $this->prefix( 'filter_plugin_submenu_items' ), array( $this, 'filter_addPluginSubMenuItem' ), $nMenuPriority );
|
122 |
add_filter( $this->prefix( 'collect_module_summary_data' ), array( $this, 'addModuleSummaryData' ), $nMenuPriority );
|
|
|
123 |
add_action( $this->prefix( 'plugin_shutdown' ), array( $this, 'action_doFeatureShutdown' ) );
|
124 |
add_action( $this->prefix( 'delete_plugin' ), array( $this, 'deletePluginOptions' ) );
|
125 |
add_filter( $this->prefix( 'aggregate_all_plugin_options' ), array( $this, 'aggregateOptionsValues' ) );
|
@@ -627,6 +628,14 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
627 |
return $aSummaryData;
|
628 |
}
|
629 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
630 |
/**
|
631 |
* @return array
|
632 |
*/
|
120 |
$nMenuPriority = isset( $aModProps[ 'menu_priority' ] ) ? $aModProps[ 'menu_priority' ] : 100;
|
121 |
add_filter( $this->prefix( 'filter_plugin_submenu_items' ), array( $this, 'filter_addPluginSubMenuItem' ), $nMenuPriority );
|
122 |
add_filter( $this->prefix( 'collect_module_summary_data' ), array( $this, 'addModuleSummaryData' ), $nMenuPriority );
|
123 |
+
add_filter( $this->prefix( 'collect_notices' ), array( $this, 'addInsightsNoticeData' ) );
|
124 |
add_action( $this->prefix( 'plugin_shutdown' ), array( $this, 'action_doFeatureShutdown' ) );
|
125 |
add_action( $this->prefix( 'delete_plugin' ), array( $this, 'deletePluginOptions' ) );
|
126 |
add_filter( $this->prefix( 'aggregate_all_plugin_options' ), array( $this, 'aggregateOptionsValues' ) );
|
628 |
return $aSummaryData;
|
629 |
}
|
630 |
|
631 |
+
/**
|
632 |
+
* @param array $aAllNotices
|
633 |
+
* @return array
|
634 |
+
*/
|
635 |
+
public function addInsightsNoticeData( $aAllNotices ) {
|
636 |
+
return $aAllNotices;
|
637 |
+
}
|
638 |
+
|
639 |
/**
|
640 |
* @return array
|
641 |
*/
|
@@ -637,6 +637,106 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
|
|
637 |
return $aWarnings;
|
638 |
}
|
639 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
640 |
/**
|
641 |
* @param array $aOptionsParams
|
642 |
* @return array
|
637 |
return $aWarnings;
|
638 |
}
|
639 |
|
640 |
+
/**
|
641 |
+
* @param array $aAllNotices
|
642 |
+
* @return array
|
643 |
+
*/
|
644 |
+
public function addInsightsNoticeData( $aAllNotices ) {
|
645 |
+
$aNotices = array(
|
646 |
+
'title' => _wpsf__( 'Scans' ),
|
647 |
+
'messages' => array()
|
648 |
+
);
|
649 |
+
|
650 |
+
{// Core files
|
651 |
+
if ( !$this->isWcfScanEnabled() ) {
|
652 |
+
$aNotices[ 'messages' ][ 'wcf' ] = array(
|
653 |
+
'title' => 'WP Core Files',
|
654 |
+
'message' => _wpsf__( 'Core File scanner is not enabled.' ),
|
655 |
+
'href' => $this->getUrl_AdminPage(),
|
656 |
+
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
657 |
+
'rec' => _wpsf__( 'Automatic WordPress Core File scanner should be turned-on.' )
|
658 |
+
);
|
659 |
+
}
|
660 |
+
else if ( $this->getScanHasProblem( 'wcf' ) ) {
|
661 |
+
$aNotices[ 'messages' ][ 'wcf' ] = array(
|
662 |
+
'title' => 'WP Core Files',
|
663 |
+
'message' => _wpsf__( 'Modified WordPress core files found.' ),
|
664 |
+
'href' => $this->getUrl_Wizard( 'wcf' ),
|
665 |
+
'action' => _wpsf__( 'Run Scan' ),
|
666 |
+
'rec' => _wpsf__( 'Scan WP core files and repair any files that are flagged as modified.' )
|
667 |
+
);
|
668 |
+
}
|
669 |
+
}
|
670 |
+
|
671 |
+
{// Unrecognised
|
672 |
+
if ( !$this->isUfcEnabled() ) {
|
673 |
+
$aNotices[ 'messages' ][ 'ufc' ] = array(
|
674 |
+
'title' => 'Unrecognised Files',
|
675 |
+
'message' => _wpsf__( 'Unrecognised File scanner is not enabled.' ),
|
676 |
+
'href' => $this->getUrl_AdminPage(),
|
677 |
+
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
678 |
+
'rec' => _wpsf__( 'Automatic scanning for non-WordPress core files is recommended.' )
|
679 |
+
);
|
680 |
+
}
|
681 |
+
else if ( $this->getScanHasProblem( 'ufc' ) ) {
|
682 |
+
$aNotices[ 'messages' ][ 'ufc' ] = array(
|
683 |
+
'title' => 'Unrecognised Files',
|
684 |
+
'message' => _wpsf__( 'Unrecognised files found in WordPress Core directory.' ),
|
685 |
+
'href' => $this->getUrl_Wizard( 'ufc' ),
|
686 |
+
'action' => _wpsf__( 'Run Scan' ),
|
687 |
+
'rec' => _wpsf__( 'Scan and remove any files that are not meant to be in the WP core directories.' )
|
688 |
+
);
|
689 |
+
}
|
690 |
+
}
|
691 |
+
|
692 |
+
{// Plugin/Theme Guard
|
693 |
+
if ( !$this->isPtgEnabled() ) {
|
694 |
+
$aNotices[ 'messages' ][ 'ptg' ] = array(
|
695 |
+
'title' => 'Plugin/Theme Guard',
|
696 |
+
'message' => _wpsf__( 'Automatic Plugin/Themes Guard is not enabled.' ),
|
697 |
+
'href' => $this->getUrl_AdminPage(),
|
698 |
+
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
699 |
+
'rec' => _wpsf__( 'Automatic detection of plugin/theme modifications is recommended.' )
|
700 |
+
);
|
701 |
+
}
|
702 |
+
else if ( $this->getScanHasProblem( 'ptg' ) ) {
|
703 |
+
$aNotices[ 'messages' ][ 'ptg' ] = array(
|
704 |
+
'title' => 'Plugin/Theme Guard',
|
705 |
+
'message' => _wpsf__( 'A plugin/theme was found to have been modified.' ),
|
706 |
+
'href' => $this->getUrl_Wizard( 'ptg' ),
|
707 |
+
'action' => _wpsf__( 'Run Scan' ),
|
708 |
+
'rec' => _wpsf__( 'Reviewing modifications to your plugins/themes is recommended.' )
|
709 |
+
);
|
710 |
+
}
|
711 |
+
}
|
712 |
+
|
713 |
+
{// Vulnerability Scanner
|
714 |
+
if ( !$this->isWpvulnEnabled() ) {
|
715 |
+
$aNotices[ 'messages' ][ 'wpv' ] = array(
|
716 |
+
'title' => 'Vulnerability Scanner',
|
717 |
+
'message' => _wpsf__( 'Plugin Vulnerability Scanner is not enabled.' ),
|
718 |
+
'href' => $this->getUrl_AdminPage(),
|
719 |
+
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
720 |
+
'rec' => _wpsf__( 'Automatic detection of plugin vulnerabilities is recommended.' )
|
721 |
+
);
|
722 |
+
}
|
723 |
+
else if ( $this->getScanHasProblem( 'wpv' ) ) {
|
724 |
+
$aNotices[ 'messages' ][ 'wpv' ] = array(
|
725 |
+
'title' => 'Vulnerable Plugins',
|
726 |
+
'message' => _wpsf__( 'At least 1 plugin has known vulnerabilities.' ),
|
727 |
+
'href' => $this->loadWp()->getAdminUrl_Plugins( true ),
|
728 |
+
'action' => sprintf( 'Go To %s', _wpsf__( 'Plugins' ) ),
|
729 |
+
'rec' => _wpsf__( 'Plugins with known vulnerabilities should be updated, removed, or replaced.' )
|
730 |
+
);
|
731 |
+
}
|
732 |
+
}
|
733 |
+
|
734 |
+
$aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
|
735 |
+
|
736 |
+
$aAllNotices[ 'scans' ] = $aNotices;
|
737 |
+
return $aAllNotices;
|
738 |
+
}
|
739 |
+
|
740 |
/**
|
741 |
* @param array $aOptionsParams
|
742 |
* @return array
|
@@ -12,19 +12,20 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
12 |
* @param array $aData
|
13 |
*/
|
14 |
protected function displayModulePage( $aData = array() ) {
|
15 |
-
$oWp = $this->loadWp();
|
16 |
|
17 |
$aRecentAuditTrail = $this->getRecentAuditTrailEntries();
|
18 |
$aSecNotices = $this->getNotices();
|
|
|
|
|
19 |
$aData = array(
|
20 |
'vars' => array(
|
21 |
-
'activation_url' => $oWp->getHomeUrl(),
|
22 |
'summary' => $this->getInsightsModsSummary(),
|
23 |
'audit_trail_recent' => $aRecentAuditTrail,
|
24 |
'insight_events' => $this->getRecentEvents(),
|
25 |
'insight_notices' => $aSecNotices,
|
26 |
'insight_notices_count' => count( $aSecNotices ),
|
27 |
'insight_stats' => $this->getStats(),
|
|
|
28 |
),
|
29 |
'inputs' => array(
|
30 |
'license_key' => array(
|
@@ -33,14 +34,12 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
33 |
)
|
34 |
),
|
35 |
'ajax' => array(
|
36 |
-
'
|
37 |
-
'
|
38 |
),
|
39 |
-
'
|
40 |
'shield_pro_url' => 'http://icwp.io/shieldpro',
|
41 |
'shield_pro_more_info_url' => 'http://icwp.io/shld1',
|
42 |
-
'iframe_url' => $this->getDef( 'landing_page_url' ),
|
43 |
-
'keyless_cp' => $this->getDef( 'keyless_cp' ),
|
44 |
),
|
45 |
'flags' => array(
|
46 |
'has_audit_trail_entries' => !empty( $aRecentAuditTrail ),
|
@@ -48,13 +47,114 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
48 |
'show_standard_options' => false,
|
49 |
'show_alt_content' => true,
|
50 |
'is_pro' => $this->isPremium(),
|
51 |
-
'has_notices' => count( $aSecNotices ) > 0
|
|
|
|
|
52 |
),
|
53 |
'strings' => $this->getDisplayStrings(),
|
54 |
);
|
55 |
echo $this->renderTemplate( '/wpadmin_pages/insights/index.twig', $aData, true );
|
56 |
}
|
57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
/**
|
59 |
* @return array
|
60 |
*/
|
@@ -86,14 +186,31 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
86 |
* @return string[]
|
87 |
*/
|
88 |
protected function getNotices() {
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
);
|
98 |
}
|
99 |
|
@@ -154,76 +271,14 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
154 |
}
|
155 |
}
|
156 |
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
*/
|
164 |
-
protected function getNoticesUsers() {
|
165 |
-
$oWpUsers = $this->loadWpUsers();
|
166 |
-
|
167 |
-
/** @var ICWP_WPSF_FeatureHandler_UserManagement $oModUsers */
|
168 |
-
$oModUsers = $this->getConn()->getModule( 'user_management' );
|
169 |
-
|
170 |
-
$aNotices = array(
|
171 |
-
'title' => _wpsf__( 'Users' ),
|
172 |
-
'messages' => array()
|
173 |
-
);
|
174 |
-
|
175 |
-
{ //admin user
|
176 |
-
$oAdmin = $oWpUsers->getUserByUsername( 'admin' );
|
177 |
-
if ( !empty( $oAdmin ) && user_can( $oAdmin, 'manage_options' ) ) {
|
178 |
-
$aNotices[ 'messages' ][ 'admin' ] = array(
|
179 |
-
'title' => 'Admin User',
|
180 |
-
'message' => sprintf( _wpsf__( "Default 'admin' user still available." ) ),
|
181 |
'href' => '',
|
182 |
-
'rec' => _wpsf__(
|
183 |
-
);
|
184 |
-
}
|
185 |
-
}
|
186 |
-
|
187 |
-
{//password policies
|
188 |
-
if ( !$oModUsers->isPasswordPoliciesEnabled() ) {
|
189 |
-
$aNotices[ 'messages' ][ 'password' ] = array(
|
190 |
-
'title' => 'Password Policies',
|
191 |
-
'message' => _wpsf__( "Strong password policies are not enforced." ),
|
192 |
-
'href' => $oModUsers->getUrl_AdminPage(),
|
193 |
-
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
194 |
-
'rec' => _wpsf__( 'Password policies should be turned-on.' )
|
195 |
-
);
|
196 |
-
}
|
197 |
-
}
|
198 |
-
|
199 |
-
$aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
|
200 |
-
return $aNotices;
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* @return array
|
205 |
-
*/
|
206 |
-
protected function getNoticesShield() {
|
207 |
-
|
208 |
-
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oModSecAdmin */
|
209 |
-
$oModSecAdmin = $this->getConn()->getModule( 'admin_access_restriction' );
|
210 |
-
|
211 |
-
$aNotices = array(
|
212 |
-
'title' => _wpsf__( 'Shield Security' ),
|
213 |
-
'messages' => array()
|
214 |
-
);
|
215 |
-
|
216 |
-
{//sec admin
|
217 |
-
if ( !( $oModSecAdmin->isModuleEnabled() && $oModSecAdmin->hasAccessKey() ) ) {
|
218 |
-
$aNotices[ 'messages' ][ 'sec_admin' ] = array(
|
219 |
-
'title' => 'Security Admin',
|
220 |
-
'message' => sprintf(
|
221 |
-
_wpsf__( "The Security Admin protection is not active." ),
|
222 |
-
$this->getConn()->getHumanName()
|
223 |
-
),
|
224 |
-
'href' => $oModSecAdmin->getUrl_AdminPage(),
|
225 |
-
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
226 |
-
'rec' => _wpsf__( 'Security Admin should be turned-on to protect your security settings.' )
|
227 |
);
|
228 |
}
|
229 |
}
|
@@ -242,8 +297,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
242 |
'messages' => array()
|
243 |
);
|
244 |
|
245 |
-
// Inactive
|
246 |
-
{
|
247 |
$nCount = 0;
|
248 |
$aActivePlugs = $oWpPlugins->getActivePlugins();
|
249 |
foreach ( $oWpPlugins->getPlugins() as $sFile => $aPlugData ) {
|
@@ -262,8 +316,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
262 |
}
|
263 |
}
|
264 |
|
265 |
-
// updates
|
266 |
-
{
|
267 |
$nCount = count( $oWpPlugins->getUpdates() );
|
268 |
if ( $nCount > 0 ) {
|
269 |
$aNotices[ 'messages' ][ 'updates' ] = array(
|
@@ -290,9 +343,8 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
290 |
'messages' => array()
|
291 |
);
|
292 |
|
293 |
-
// Inactive
|
294 |
-
|
295 |
-
$nInactive = count( $oWpT->getThemes() ) - 1;
|
296 |
if ( $nInactive > 0 ) {
|
297 |
$aNotices[ 'messages' ][ 'inactive' ] = array(
|
298 |
'title' => 'Inactive',
|
@@ -304,8 +356,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
304 |
}
|
305 |
}
|
306 |
|
307 |
-
// updates
|
308 |
-
{
|
309 |
$nCount = count( $oWpT->getUpdates() );
|
310 |
if ( $nCount > 0 ) {
|
311 |
$aNotices[ 'messages' ][ 'updates' ] = array(
|
@@ -332,8 +383,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
332 |
'messages' => array()
|
333 |
);
|
334 |
|
335 |
-
// updates
|
336 |
-
{
|
337 |
if ( $oWp->hasCoreUpdate() ) {
|
338 |
$aNotices[ 'messages' ][ 'updates' ] = array(
|
339 |
'title' => 'Updates',
|
@@ -345,8 +395,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
345 |
}
|
346 |
}
|
347 |
|
348 |
-
//
|
349 |
-
{
|
350 |
if ( !$oWp->canCoreUpdateAutomatically() ) {
|
351 |
$aNotices[ 'messages' ][ 'updates_auto' ] = array(
|
352 |
'title' => 'Auto Updates',
|
@@ -358,31 +407,6 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
358 |
}
|
359 |
}
|
360 |
|
361 |
-
{ // Disallow file edit
|
362 |
-
if ( current_user_can( 'edit_plugins' ) ) { //assumes current user is admin
|
363 |
-
$aNotices[ 'messages' ][ 'disallow_file_edit' ] = array(
|
364 |
-
'title' => 'Code Editor',
|
365 |
-
'message' => _wpsf__( 'Direct editing of plugin/theme files is permitted.' ),
|
366 |
-
'href' => $this->getConn()->getModule( 'lockdown' )->getUrl_AdminPage(),
|
367 |
-
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
368 |
-
'rec' => _wpsf__( 'WP Plugin file editing should be disabled.' )
|
369 |
-
);
|
370 |
-
}
|
371 |
-
}
|
372 |
-
|
373 |
-
{ // db password strength
|
374 |
-
$this->loadAutoload();
|
375 |
-
$nStrength = ( new \ZxcvbnPhp\Zxcvbn() )->passwordStrength( DB_PASSWORD )[ 'score' ];
|
376 |
-
if ( $nStrength < 4 ) {
|
377 |
-
$aNotices[ 'messages' ][ 'db_strength' ] = array(
|
378 |
-
'title' => 'DB Password',
|
379 |
-
'message' => _wpsf__( 'DB Password appears to be weak.' ),
|
380 |
-
'href' => '',
|
381 |
-
'rec' => _wpsf__( 'The database password should be strong.' )
|
382 |
-
);
|
383 |
-
}
|
384 |
-
}
|
385 |
-
|
386 |
$aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
|
387 |
return $aNotices;
|
388 |
}
|
@@ -390,105 +414,24 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
390 |
/**
|
391 |
* @return array
|
392 |
*/
|
393 |
-
protected function
|
394 |
-
$
|
395 |
-
|
396 |
-
'messages' => array()
|
397 |
-
);
|
398 |
-
|
399 |
-
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oModHg */
|
400 |
-
$oModHg = $this->getConn()->getModule( 'hack_protect' );
|
401 |
-
|
402 |
-
// Core files
|
403 |
-
{
|
404 |
-
if ( !$oModHg->isWcfScanEnabled() ) {
|
405 |
-
$aNotices[ 'messages' ][ 'wcf' ] = array(
|
406 |
-
'title' => 'WP Core Files',
|
407 |
-
'message' => _wpsf__( 'Core File scanner is not enabled.' ),
|
408 |
-
'href' => $oModHg->getUrl_AdminPage(),
|
409 |
-
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
410 |
-
'rec' => _wpsf__( 'Automatic WordPress Core File scanner should be turned-on.' )
|
411 |
-
);
|
412 |
-
}
|
413 |
-
else if ( $oModHg->getScanHasProblem( 'wcf' ) ) {
|
414 |
-
$aNotices[ 'messages' ][ 'wcf' ] = array(
|
415 |
-
'title' => 'WP Core Files',
|
416 |
-
'message' => _wpsf__( 'Modified WordPress core files found.' ),
|
417 |
-
'href' => $oModHg->getUrl_Wizard( 'wcf' ),
|
418 |
-
'action' => _wpsf__( 'Run Scan' ),
|
419 |
-
'rec' => _wpsf__( 'Scan WP core files and repair any files that are flagged as modified.' )
|
420 |
-
);
|
421 |
-
}
|
422 |
-
}
|
423 |
-
|
424 |
-
// Unrecognised
|
425 |
-
{
|
426 |
-
if ( !$oModHg->isUfcEnabled() ) {
|
427 |
-
$aNotices[ 'messages' ][ 'ufc' ] = array(
|
428 |
-
'title' => 'Unrecognised Files',
|
429 |
-
'message' => _wpsf__( 'Unrecognised File scanner is not enabled.' ),
|
430 |
-
'href' => $oModHg->getUrl_AdminPage(),
|
431 |
-
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
432 |
-
'rec' => _wpsf__( 'Automatic scanning for non-WordPress core files is recommended.' )
|
433 |
-
);
|
434 |
-
}
|
435 |
-
else if ( $oModHg->getScanHasProblem( 'ufc' ) ) {
|
436 |
-
$aNotices[ 'messages' ][ 'ufc' ] = array(
|
437 |
-
'title' => 'Unrecognised Files',
|
438 |
-
'message' => _wpsf__( 'Unrecognised files found in WordPress Core directory.' ),
|
439 |
-
'href' => $oModHg->getUrl_Wizard( 'ufc' ),
|
440 |
-
'action' => _wpsf__( 'Run Scan' ),
|
441 |
-
'rec' => _wpsf__( 'Scan and remove any files that are not meant to be in the WP core directories.' )
|
442 |
-
);
|
443 |
-
}
|
444 |
-
}
|
445 |
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
'message' => _wpsf__( 'Automatic Plugin/Themes Guard is not enabled.' ),
|
452 |
-
'href' => $oModHg->getUrl_AdminPage(),
|
453 |
-
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
454 |
-
'rec' => _wpsf__( 'Automatic detection of plugin/theme modifications is recommended.' )
|
455 |
-
);
|
456 |
-
}
|
457 |
-
else if ( $oModHg->getScanHasProblem( 'ptg' ) ) {
|
458 |
-
$aNotices[ 'messages' ][ 'ptg' ] = array(
|
459 |
-
'title' => 'Plugin/Theme Guard',
|
460 |
-
'message' => _wpsf__( 'A plugin/theme was found to have been modified.' ),
|
461 |
-
'href' => $oModHg->getUrl_Wizard( 'ptg' ),
|
462 |
-
'action' => _wpsf__( 'Run Scan' ),
|
463 |
-
'rec' => _wpsf__( 'Reviewing modifications to your plugins/themes is recommended.' )
|
464 |
-
);
|
465 |
-
}
|
466 |
-
}
|
467 |
|
468 |
-
|
469 |
-
{
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
'message' => _wpsf__( 'Plugin Vulnerability Scanner is not enabled.' ),
|
474 |
-
'href' => $oModHg->getUrl_AdminPage(),
|
475 |
-
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
476 |
-
'rec' => _wpsf__( 'Automatic detection of plugin vulnerabilities is recommended.' )
|
477 |
-
);
|
478 |
-
}
|
479 |
-
else if ( $oModHg->getScanHasProblem( 'wpv' ) ) {
|
480 |
-
$aNotices[ 'messages' ][ 'wpv' ] = array(
|
481 |
-
'title' => 'Vulnerable Plugins',
|
482 |
-
'message' => _wpsf__( 'At least 1 plugin has known vulnerabilities.' ),
|
483 |
-
'href' => $this->loadWp()->getAdminUrl_Plugins( true ),
|
484 |
-
'action' => sprintf( 'Go To %s', _wpsf__( 'Plugins' ) ),
|
485 |
-
'rec' => _wpsf__( 'Plugins with known vulnerabilities should be updated, removed, or replaced.' )
|
486 |
-
);
|
487 |
-
}
|
488 |
}
|
489 |
|
490 |
-
|
491 |
-
return $aNotices;
|
492 |
}
|
493 |
|
494 |
/**
|
@@ -598,63 +541,6 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
598 |
return $aItems;
|
599 |
}
|
600 |
|
601 |
-
/**
|
602 |
-
* @param array $aOptionsParams
|
603 |
-
* @return array
|
604 |
-
* @throws Exception
|
605 |
-
*/
|
606 |
-
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
607 |
-
|
608 |
-
$sSectionSlug = $aOptionsParams[ 'slug' ];
|
609 |
-
switch ( $sSectionSlug ) {
|
610 |
-
|
611 |
-
case 'section_email_options' :
|
612 |
-
$sTitle = _wpsf__( 'Email Options' );
|
613 |
-
break;
|
614 |
-
|
615 |
-
default:
|
616 |
-
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
617 |
-
}
|
618 |
-
$aOptionsParams[ 'title' ] = $sTitle;
|
619 |
-
return $aOptionsParams;
|
620 |
-
}
|
621 |
-
|
622 |
-
/**
|
623 |
-
* @param array $aOptionsParams
|
624 |
-
* @return array
|
625 |
-
* @throws Exception
|
626 |
-
*/
|
627 |
-
protected function loadStrings_Options( $aOptionsParams ) {
|
628 |
-
|
629 |
-
$sKey = $aOptionsParams[ 'key' ];
|
630 |
-
switch ( $sKey ) {
|
631 |
-
case 'send_email_throttle_limit' :
|
632 |
-
$sName = _wpsf__( 'Email Throttle Limit' );
|
633 |
-
$sSummary = _wpsf__( 'Limit Emails Per Second' );
|
634 |
-
$sDescription = _wpsf__( 'You throttle emails sent by this plugin by limiting the number of emails sent every second. This is useful in case you get hit by a bot attack. Zero (0) turns this off. Suggested: 10' );
|
635 |
-
break;
|
636 |
-
|
637 |
-
default:
|
638 |
-
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
639 |
-
}
|
640 |
-
|
641 |
-
$aOptionsParams[ 'name' ] = $sName;
|
642 |
-
$aOptionsParams[ 'summary' ] = $sSummary;
|
643 |
-
$aOptionsParams[ 'description' ] = $sDescription;
|
644 |
-
return $aOptionsParams;
|
645 |
-
}
|
646 |
-
|
647 |
-
/**
|
648 |
-
* This is the point where you would want to do any options verification
|
649 |
-
*/
|
650 |
-
protected function doPrePluginOptionsSave() {
|
651 |
-
$sLimit = $this->getOpt( 'send_email_throttle_limit' );
|
652 |
-
if ( !is_numeric( $sLimit ) || $sLimit < 0 ) {
|
653 |
-
$sLimit = 0;
|
654 |
-
}
|
655 |
-
$this->setOpt( 'send_email_throttle_limit', $sLimit );
|
656 |
-
}
|
657 |
-
|
658 |
/**
|
659 |
* @return string[]
|
660 |
*/
|
12 |
* @param array $aData
|
13 |
*/
|
14 |
protected function displayModulePage( $aData = array() ) {
|
|
|
15 |
|
16 |
$aRecentAuditTrail = $this->getRecentAuditTrailEntries();
|
17 |
$aSecNotices = $this->getNotices();
|
18 |
+
$aNotes = $this->getNotes();
|
19 |
+
|
20 |
$aData = array(
|
21 |
'vars' => array(
|
|
|
22 |
'summary' => $this->getInsightsModsSummary(),
|
23 |
'audit_trail_recent' => $aRecentAuditTrail,
|
24 |
'insight_events' => $this->getRecentEvents(),
|
25 |
'insight_notices' => $aSecNotices,
|
26 |
'insight_notices_count' => count( $aSecNotices ),
|
27 |
'insight_stats' => $this->getStats(),
|
28 |
+
'insight_notes' => $aNotes,
|
29 |
),
|
30 |
'inputs' => array(
|
31 |
'license_key' => array(
|
34 |
)
|
35 |
),
|
36 |
'ajax' => array(
|
37 |
+
'admin_note_new' => $this->getAjaxActionData( 'admin_note_new' ),
|
38 |
+
'admin_notes_render' => $this->getAjaxActionData( 'admin_notes_render' ),
|
39 |
),
|
40 |
+
'hrefs' => array(
|
41 |
'shield_pro_url' => 'http://icwp.io/shieldpro',
|
42 |
'shield_pro_more_info_url' => 'http://icwp.io/shld1',
|
|
|
|
|
43 |
),
|
44 |
'flags' => array(
|
45 |
'has_audit_trail_entries' => !empty( $aRecentAuditTrail ),
|
47 |
'show_standard_options' => false,
|
48 |
'show_alt_content' => true,
|
49 |
'is_pro' => $this->isPremium(),
|
50 |
+
'has_notices' => count( $aSecNotices ) > 0,
|
51 |
+
'has_notes' => count( $aNotes ) > 0,
|
52 |
+
'can_notes' => $this->isPremium() //not the way to determine
|
53 |
),
|
54 |
'strings' => $this->getDisplayStrings(),
|
55 |
);
|
56 |
echo $this->renderTemplate( '/wpadmin_pages/insights/index.twig', $aData, true );
|
57 |
}
|
58 |
|
59 |
+
public function insertCustomJsVars() {
|
60 |
+
|
61 |
+
if ( $this->isThisModulePage() ) {
|
62 |
+
wp_localize_script(
|
63 |
+
$this->prefix( 'plugin' ),
|
64 |
+
'icwp_wpsf_vars_insights',
|
65 |
+
array(
|
66 |
+
'ajax_admin_notes_render' => $this->getAjaxActionData( 'admin_notes_render' ),
|
67 |
+
)
|
68 |
+
);
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* @param array $aAjaxResponse
|
74 |
+
* @return array
|
75 |
+
*/
|
76 |
+
public function handleAuthAjax( $aAjaxResponse ) {
|
77 |
+
|
78 |
+
if ( empty( $aAjaxResponse ) ) {
|
79 |
+
switch ( $this->loadDP()->request( 'exec' ) ) {
|
80 |
+
|
81 |
+
case 'admin_note_new':
|
82 |
+
$aAjaxResponse = $this->ajaxExec_AdminNoteNew();
|
83 |
+
break;
|
84 |
+
|
85 |
+
case 'admin_notes_render':
|
86 |
+
$aAjaxResponse = $this->ajaxExec_AdminNotesRender();
|
87 |
+
break;
|
88 |
+
|
89 |
+
default:
|
90 |
+
break;
|
91 |
+
}
|
92 |
+
}
|
93 |
+
return parent::handleAuthAjax( $aAjaxResponse );
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* @return array
|
98 |
+
*/
|
99 |
+
protected function ajaxExec_AdminNoteNew() {
|
100 |
+
$oDP = $this->loadDP();
|
101 |
+
/** @var ICWP_WPSF_FeatureHandler_Plugin $oMod */
|
102 |
+
$oMod = $this->getConn()->getModule( 'plugin' );
|
103 |
+
$sNote = trim( $oDP->post( 'admin_note', '' ) );
|
104 |
+
|
105 |
+
$bSuccess = false;
|
106 |
+
if ( !$oMod->getCanAdminNotes() ) {
|
107 |
+
$sMessage = _wpsf__( 'Sorry, Admin Notes is only available for Shield Pro.' );
|
108 |
+
}
|
109 |
+
else if ( empty( $sNote ) ) {
|
110 |
+
$sMessage = _wpsf__( 'Sorry, but it appears your note was empty.' );
|
111 |
+
}
|
112 |
+
else {
|
113 |
+
/** @var ICWP_WPSF_Processor_Plugin $oP */
|
114 |
+
$oP = $this->getConn()->getModule( 'plugin' )->getProcessor();
|
115 |
+
$bSuccess = $oP->getSubProcessorNotes()
|
116 |
+
->getQueryCreator()
|
117 |
+
->create( $sNote ) !== false;
|
118 |
+
|
119 |
+
$sMessage = $bSuccess ? _wpsf__( 'Note created successfully.' ) : _wpsf__( 'Note could not be created.' );
|
120 |
+
}
|
121 |
+
return array(
|
122 |
+
'success' => $bSuccess,
|
123 |
+
'message' => $sMessage
|
124 |
+
);
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* @return array
|
129 |
+
*/
|
130 |
+
protected function ajaxExec_AdminNotesRender() {
|
131 |
+
$oDP = $this->loadDP();
|
132 |
+
/** @var ICWP_WPSF_FeatureHandler_Plugin $oMod */
|
133 |
+
$oMod = $this->getConn()->getModule( 'plugin' );
|
134 |
+
$sNote = trim( $oDP->post( 'admin_note', '' ) );
|
135 |
+
|
136 |
+
$aNotes = $this->getNotes();
|
137 |
+
$sHtml = $this->renderTemplate(
|
138 |
+
'/wpadmin_pages/insights/admin_notes_table.twig',
|
139 |
+
array(
|
140 |
+
'vars' => array(
|
141 |
+
'insight_notes' => $aNotes,
|
142 |
+
),
|
143 |
+
'flags' => array(
|
144 |
+
'has_notes' => count( $aNotes ) > 0,
|
145 |
+
'can_notes' => $this->isPremium() //not the way to determine
|
146 |
+
),
|
147 |
+
),
|
148 |
+
true
|
149 |
+
);
|
150 |
+
|
151 |
+
$bSuccess = true;
|
152 |
+
return array(
|
153 |
+
'success' => $bSuccess,
|
154 |
+
'html' => $sHtml
|
155 |
+
);
|
156 |
+
}
|
157 |
+
|
158 |
/**
|
159 |
* @return array
|
160 |
*/
|
186 |
* @return string[]
|
187 |
*/
|
188 |
protected function getNotices() {
|
189 |
+
|
190 |
+
$aAll = apply_filters(
|
191 |
+
$this->prefix( 'collect_notices' ),
|
192 |
+
array(
|
193 |
+
'plugins' => $this->getNoticesPlugins(),
|
194 |
+
'themes' => $this->getNoticesThemes(),
|
195 |
+
'core' => $this->getNoticesCore(),
|
196 |
+
)
|
197 |
+
);
|
198 |
+
|
199 |
+
// order and then remove empties
|
200 |
+
return array_filter(
|
201 |
+
array_merge(
|
202 |
+
array(
|
203 |
+
'site' => array(),
|
204 |
+
'sec_admin' => array(),
|
205 |
+
'scans' => array(),
|
206 |
+
'core' => array(),
|
207 |
+
'plugins' => array(),
|
208 |
+
'themes' => array(),
|
209 |
+
'users' => array(),
|
210 |
+
'lockdown' => array(),
|
211 |
+
),
|
212 |
+
$aAll
|
213 |
+
)
|
214 |
);
|
215 |
}
|
216 |
|
271 |
}
|
272 |
}
|
273 |
|
274 |
+
{ // db password strength
|
275 |
+
$nStrength = ( new \ZxcvbnPhp\Zxcvbn() )->passwordStrength( DB_PASSWORD )[ 'score' ];
|
276 |
+
if ( $nStrength < 4 ) {
|
277 |
+
$aNotices[ 'messages' ][ 'db_strength' ] = array(
|
278 |
+
'title' => 'DB Password',
|
279 |
+
'message' => _wpsf__( 'DB Password appears to be weak.' ),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
280 |
'href' => '',
|
281 |
+
'rec' => _wpsf__( 'The database password should be strong.' )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
282 |
);
|
283 |
}
|
284 |
}
|
297 |
'messages' => array()
|
298 |
);
|
299 |
|
300 |
+
{// Inactive
|
|
|
301 |
$nCount = 0;
|
302 |
$aActivePlugs = $oWpPlugins->getActivePlugins();
|
303 |
foreach ( $oWpPlugins->getPlugins() as $sFile => $aPlugData ) {
|
316 |
}
|
317 |
}
|
318 |
|
319 |
+
{// updates
|
|
|
320 |
$nCount = count( $oWpPlugins->getUpdates() );
|
321 |
if ( $nCount > 0 ) {
|
322 |
$aNotices[ 'messages' ][ 'updates' ] = array(
|
343 |
'messages' => array()
|
344 |
);
|
345 |
|
346 |
+
{// Inactive
|
347 |
+
$nInactive = count( $oWpT->getThemes() ) - ( $oWpT->isActiveThemeAChild() ? 2 : 1 );
|
|
|
348 |
if ( $nInactive > 0 ) {
|
349 |
$aNotices[ 'messages' ][ 'inactive' ] = array(
|
350 |
'title' => 'Inactive',
|
356 |
}
|
357 |
}
|
358 |
|
359 |
+
{// updates
|
|
|
360 |
$nCount = count( $oWpT->getUpdates() );
|
361 |
if ( $nCount > 0 ) {
|
362 |
$aNotices[ 'messages' ][ 'updates' ] = array(
|
383 |
'messages' => array()
|
384 |
);
|
385 |
|
386 |
+
{// updates
|
|
|
387 |
if ( $oWp->hasCoreUpdate() ) {
|
388 |
$aNotices[ 'messages' ][ 'updates' ] = array(
|
389 |
'title' => 'Updates',
|
395 |
}
|
396 |
}
|
397 |
|
398 |
+
{// autoupdates
|
|
|
399 |
if ( !$oWp->canCoreUpdateAutomatically() ) {
|
400 |
$aNotices[ 'messages' ][ 'updates_auto' ] = array(
|
401 |
'title' => 'Auto Updates',
|
407 |
}
|
408 |
}
|
409 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
410 |
$aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
|
411 |
return $aNotices;
|
412 |
}
|
414 |
/**
|
415 |
* @return array
|
416 |
*/
|
417 |
+
protected function getNotes() {
|
418 |
+
/** @var ICWP_WPSF_Processor_Plugin $oProc */
|
419 |
+
$oProc = $this->getConn()->getModule( 'plugin' )->getProcessor();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
420 |
|
421 |
+
$oRetriever = $oProc->getSubProcessorNotes()
|
422 |
+
->getQueryRetriever();
|
423 |
+
$aNotes = $oRetriever->setLimit( 10 )
|
424 |
+
->setResultsAsVo( false )
|
425 |
+
->all();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
426 |
|
427 |
+
$oWP = $this->loadWp();
|
428 |
+
foreach ( $aNotes as $oItem ) {
|
429 |
+
$oItem->created_at = $oWP->getTimeStringForDisplay( $oItem->created_at );
|
430 |
+
$oItem->note = stripslashes( sanitize_text_field( $oItem->note ) );
|
431 |
+
$oItem->wp_username = sanitize_text_field( $oItem->wp_username );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
432 |
}
|
433 |
|
434 |
+
return $aNotes;
|
|
|
435 |
}
|
436 |
|
437 |
/**
|
541 |
return $aItems;
|
542 |
}
|
543 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
544 |
/**
|
545 |
* @return string[]
|
546 |
*/
|
@@ -50,6 +50,34 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWps
|
|
50 |
return parent::isReadyToExecute() && !$this->isVisitorWhitelisted();
|
51 |
}
|
52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
/**
|
54 |
* @param array $aOptionsParams
|
55 |
* @return array
|
50 |
return parent::isReadyToExecute() && !$this->isVisitorWhitelisted();
|
51 |
}
|
52 |
|
53 |
+
/**
|
54 |
+
* @param array $aAllNotices
|
55 |
+
* @return array
|
56 |
+
*/
|
57 |
+
public function addInsightsNoticeData( $aAllNotices ) {
|
58 |
+
$aNotices = array(
|
59 |
+
'title' => _wpsf__( 'Lockdown' ),
|
60 |
+
'messages' => array()
|
61 |
+
);
|
62 |
+
|
63 |
+
{ //edit plugins
|
64 |
+
if ( current_user_can( 'edit_plugins' ) ) { //assumes current user is admin
|
65 |
+
$aNotices[ 'messages' ][ 'disallow_file_edit' ] = array(
|
66 |
+
'title' => 'Code Editor',
|
67 |
+
'message' => _wpsf__( 'Direct editing of plugin/theme files is permitted.' ),
|
68 |
+
'href' => $this->getUrl_AdminPage(),
|
69 |
+
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
70 |
+
'rec' => _wpsf__( 'WP Plugin file editing should be disabled.' )
|
71 |
+
);
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
$aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
|
76 |
+
|
77 |
+
$aAllNotices[ 'lockdown' ] = $aNotices;
|
78 |
+
return $aAllNotices;
|
79 |
+
}
|
80 |
+
|
81 |
/**
|
82 |
* @param array $aOptionsParams
|
83 |
* @return array
|
@@ -671,6 +671,20 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
671 |
return $this;
|
672 |
}
|
673 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
674 |
/**
|
675 |
* @param array $aOptionsParams
|
676 |
* @return array
|
@@ -749,6 +763,12 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
749 |
->getHumanName() );
|
750 |
break;
|
751 |
|
|
|
|
|
|
|
|
|
|
|
|
|
752 |
case 'enable_tracking' :
|
753 |
$sName = sprintf( _wpsf__( 'Enable %s Module' ), _wpsf__( 'Information Gathering' ) );
|
754 |
$sSummary = _wpsf__( 'Permit Anonymous Usage Information Gathering' );
|
671 |
return $this;
|
672 |
}
|
673 |
|
674 |
+
/**
|
675 |
+
* @return bool
|
676 |
+
*/
|
677 |
+
public function getCanAdminNotes() {
|
678 |
+
return true||$this->isPremium();
|
679 |
+
}
|
680 |
+
|
681 |
+
/**
|
682 |
+
* @return string
|
683 |
+
*/
|
684 |
+
public function getDbNameNotes() {
|
685 |
+
return $this->prefixOptionKey( $this->getDef( 'db_notes_name' ) );
|
686 |
+
}
|
687 |
+
|
688 |
/**
|
689 |
* @param array $aOptionsParams
|
690 |
* @return array
|
763 |
->getHumanName() );
|
764 |
break;
|
765 |
|
766 |
+
case 'enable_notes' :
|
767 |
+
$sName = sprintf( _wpsf__( 'Enable %s' ), _wpsf__( 'Admin Notes' ) );
|
768 |
+
$sSummary = _wpsf__( 'Turn-On Admin Notes Section In Insights Dashboard' );
|
769 |
+
$sDescription = _wpsf__( 'When turned-on it enables administrators to enter custom notes in the Insights Dashboard.' );
|
770 |
+
break;
|
771 |
+
|
772 |
case 'enable_tracking' :
|
773 |
$sName = sprintf( _wpsf__( 'Enable %s Module' ), _wpsf__( 'Information Gathering' ) );
|
774 |
$sSummary = _wpsf__( 'Permit Anonymous Usage Information Gathering' );
|
@@ -41,7 +41,8 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
|
|
41 |
|
42 |
return array(
|
43 |
'strings' => $this->getDisplayStrings(),
|
44 |
-
'time_now' => sprintf( _wpsf__( 'now: %s' ), date_i18n( $sTimeFormat.' '.$sDateFormat, $this->loadDP()
|
|
|
45 |
'sUserSessionsTable' => $sUserSessionsTable
|
46 |
);
|
47 |
}
|
@@ -203,6 +204,48 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
|
|
203 |
return $this->getOptIs( 'pass_prevent_pwned', 'Y' );
|
204 |
}
|
205 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
/**
|
207 |
* @param array $aOptionsParams
|
208 |
* @return array
|
41 |
|
42 |
return array(
|
43 |
'strings' => $this->getDisplayStrings(),
|
44 |
+
'time_now' => sprintf( _wpsf__( 'now: %s' ), date_i18n( $sTimeFormat.' '.$sDateFormat, $this->loadDP()
|
45 |
+
->time() ) ),
|
46 |
'sUserSessionsTable' => $sUserSessionsTable
|
47 |
);
|
48 |
}
|
204 |
return $this->getOptIs( 'pass_prevent_pwned', 'Y' );
|
205 |
}
|
206 |
|
207 |
+
/**
|
208 |
+
* @param array $aAllNotices
|
209 |
+
* @return array
|
210 |
+
*/
|
211 |
+
public function addInsightsNoticeData( $aAllNotices ) {
|
212 |
+
$oWpUsers = $this->loadWpUsers();
|
213 |
+
|
214 |
+
$aNotices = array(
|
215 |
+
'title' => _wpsf__( 'Users' ),
|
216 |
+
'messages' => array()
|
217 |
+
);
|
218 |
+
|
219 |
+
{ //admin user
|
220 |
+
$oAdmin = $oWpUsers->getUserByUsername( 'admin' );
|
221 |
+
if ( !empty( $oAdmin ) && user_can( $oAdmin, 'manage_options' ) ) {
|
222 |
+
$aNotices[ 'messages' ][ 'admin' ] = array(
|
223 |
+
'title' => 'Admin User',
|
224 |
+
'message' => sprintf( _wpsf__( "Default 'admin' user still available." ) ),
|
225 |
+
'href' => '',
|
226 |
+
'rec' => _wpsf__( "Default 'admin' user should be disabled or removed." )
|
227 |
+
);
|
228 |
+
}
|
229 |
+
}
|
230 |
+
|
231 |
+
{//password policies
|
232 |
+
if ( !$this->isPasswordPoliciesEnabled() ) {
|
233 |
+
$aNotices[ 'messages' ][ 'password' ] = array(
|
234 |
+
'title' => 'Password Policies',
|
235 |
+
'message' => _wpsf__( "Strong password policies are not enforced." ),
|
236 |
+
'href' => $this->getUrl_AdminPage(),
|
237 |
+
'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
|
238 |
+
'rec' => _wpsf__( 'Password policies should be turned-on.' )
|
239 |
+
);
|
240 |
+
}
|
241 |
+
}
|
242 |
+
|
243 |
+
$aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
|
244 |
+
|
245 |
+
$aAllNotices[ 'users' ] = $aNotices;
|
246 |
+
return $aAllNotices;
|
247 |
+
}
|
248 |
+
|
249 |
/**
|
250 |
* @param array $aOptionsParams
|
251 |
* @return array
|
@@ -293,4 +293,11 @@ abstract class ICWP_WPSF_BaseDbProcessor extends ICWP_WPSF_Processor_BaseWpsf {
|
|
293 |
protected function getAutoExpirePeriod() {
|
294 |
return null;
|
295 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
296 |
}
|
293 |
protected function getAutoExpirePeriod() {
|
294 |
return null;
|
295 |
}
|
296 |
+
|
297 |
+
/**
|
298 |
+
* @return string
|
299 |
+
*/
|
300 |
+
protected function getQueryDir() {
|
301 |
+
return dirname( dirname( __FILE__ ) ).'/query/';
|
302 |
+
}
|
303 |
}
|
@@ -96,6 +96,19 @@ class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_BasePlugin {
|
|
96 |
return $oProc;
|
97 |
}
|
98 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
/**
|
100 |
*/
|
101 |
public function dumpTrackingData() {
|
96 |
return $oProc;
|
97 |
}
|
98 |
|
99 |
+
/**
|
100 |
+
* @return ICWP_WPSF_Processor_Plugin_Notes
|
101 |
+
*/
|
102 |
+
public function getSubProcessorNotes() {
|
103 |
+
$oProc = $this->getSubProcessor( 'notes' );
|
104 |
+
if ( is_null( $oProc ) ) {
|
105 |
+
require_once( dirname( __FILE__ ).'/plugin_notes.php' );
|
106 |
+
$oProc = new ICWP_WPSF_Processor_Plugin_Notes( $this->getFeature() );
|
107 |
+
$this->aSubProcessors[ 'notes' ] = $oProc;
|
108 |
+
}
|
109 |
+
return $oProc;
|
110 |
+
}
|
111 |
+
|
112 |
/**
|
113 |
*/
|
114 |
public function dumpTrackingData() {
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( class_exists( 'ICWP_WPSF_Processor_Plugin_Notes' ) ) {
|
4 |
+
return;
|
5 |
+
}
|
6 |
+
|
7 |
+
require_once( dirname( __FILE__ ).'/basedb.php' );
|
8 |
+
|
9 |
+
class ICWP_WPSF_Processor_Plugin_Notes extends ICWP_WPSF_BaseDbProcessor {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @param ICWP_WPSF_FeatureHandler_Plugin $oFeatureOptions
|
13 |
+
* @throws Exception
|
14 |
+
*/
|
15 |
+
public function __construct( ICWP_WPSF_FeatureHandler_Plugin $oFeatureOptions ) {
|
16 |
+
parent::__construct( $oFeatureOptions, $oFeatureOptions->getDbNameNotes() );
|
17 |
+
}
|
18 |
+
|
19 |
+
public function run() {
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @return string
|
24 |
+
*/
|
25 |
+
public function getCreateTableSql() {
|
26 |
+
$sSqlTables = "CREATE TABLE %s (
|
27 |
+
id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
28 |
+
wp_username varchar(255) NOT NULL DEFAULT 'unknown',
|
29 |
+
note TEXT,
|
30 |
+
created_at int(15) UNSIGNED NOT NULL DEFAULT 0,
|
31 |
+
deleted_at int(15) UNSIGNED NOT NULL DEFAULT 0,
|
32 |
+
PRIMARY KEY (id)
|
33 |
+
) %s;";
|
34 |
+
return sprintf( $sSqlTables, $this->getTableName(), $this->loadDbProcessor()->getCharCollate() );
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @return array
|
39 |
+
*/
|
40 |
+
protected function getTableColumnsByDefinition() {
|
41 |
+
$aDef = $this->getFeature()->getDef( 'db_notes_table_columns' );
|
42 |
+
return ( is_array( $aDef ) ? $aDef : array() );
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @param string $nId
|
47 |
+
* @return bool|int
|
48 |
+
*/
|
49 |
+
public function deleteNote( $nId ) {
|
50 |
+
return $this->getQueryDeleter()->delete( $nId );
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* @param string $sNote
|
55 |
+
* @return bool|int
|
56 |
+
*/
|
57 |
+
public function insertNote( $sNote ) {
|
58 |
+
return $this->getQueryCreator()->create( $sNote );
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @return ICWP_WPSF_Query_PluginNotes_Create
|
63 |
+
*/
|
64 |
+
public function getQueryCreator() {
|
65 |
+
require_once( $this->getQueryDir().'plugin_notes_create.php' );
|
66 |
+
$oQ = new ICWP_WPSF_Query_PluginNotes_Create();
|
67 |
+
return $oQ->setTable( $this->getTableName() );
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* @return ICWP_WPSF_Query_PluginNotes_Delete
|
72 |
+
*/
|
73 |
+
public function getQueryDeleter() {
|
74 |
+
require_once( $this->getQueryDir().'plugin_notes_delete.php' );
|
75 |
+
$oQ = new ICWP_WPSF_Query_PluginNotes_Delete();
|
76 |
+
return $oQ->setTable( $this->getTableName() );
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @return ICWP_WPSF_Query_PluginNotes_Retrieve
|
81 |
+
*/
|
82 |
+
public function getQueryRetriever() {
|
83 |
+
require_once( $this->getQueryDir().'plugin_notes_retrieve.php' );
|
84 |
+
$oQ = new ICWP_WPSF_Query_PluginNotes_Retrieve();
|
85 |
+
return $oQ->setTable( $this->getTableName() );
|
86 |
+
}
|
87 |
+
}
|
@@ -262,7 +262,7 @@ class ICWP_WPSF_Processor_Sessions extends ICWP_WPSF_BaseDbProcessor {
|
|
262 |
* @return ICWP_WPSF_Query_Sessions_Retrieve
|
263 |
*/
|
264 |
public function getSessionRetriever() {
|
265 |
-
require_once(
|
266 |
$oRetrieve = new ICWP_WPSF_Query_Sessions_Retrieve();
|
267 |
return $oRetrieve->setTable( $this->getTableName() );
|
268 |
}
|
@@ -271,7 +271,7 @@ class ICWP_WPSF_Processor_Sessions extends ICWP_WPSF_BaseDbProcessor {
|
|
271 |
* @return ICWP_WPSF_Query_Sessions_Update
|
272 |
*/
|
273 |
public function getSessionUpdater() {
|
274 |
-
require_once(
|
275 |
$oUpdate = new ICWP_WPSF_Query_Sessions_Update();
|
276 |
return $oUpdate->setTable( $this->getTableName() );
|
277 |
}
|
262 |
* @return ICWP_WPSF_Query_Sessions_Retrieve
|
263 |
*/
|
264 |
public function getSessionRetriever() {
|
265 |
+
require_once( $this->getQueryDir().'sessions_retrieve.php' );
|
266 |
$oRetrieve = new ICWP_WPSF_Query_Sessions_Retrieve();
|
267 |
return $oRetrieve->setTable( $this->getTableName() );
|
268 |
}
|
271 |
* @return ICWP_WPSF_Query_Sessions_Update
|
272 |
*/
|
273 |
public function getSessionUpdater() {
|
274 |
+
require_once( $this->getQueryDir().'sessions_update.php' );
|
275 |
$oUpdate = new ICWP_WPSF_Query_Sessions_Update();
|
276 |
return $oUpdate->setTable( $this->getTableName() );
|
277 |
}
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ICWP_WPSF_NoteVO {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @var stdClass
|
7 |
+
*/
|
8 |
+
protected $oRowData;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @param stdClass $oRowData
|
12 |
+
*/
|
13 |
+
public function __construct( $oRowData ) {
|
14 |
+
$this->oRowData = $oRowData;
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @return int
|
19 |
+
*/
|
20 |
+
public function getCreatedAt() {
|
21 |
+
return $this->getRowData()->created_at;
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @return int
|
26 |
+
*/
|
27 |
+
public function getId() {
|
28 |
+
return $this->getRowData()->id;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @return string
|
33 |
+
*/
|
34 |
+
public function getNote() {
|
35 |
+
return $this->getRowData()->note;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @return int
|
40 |
+
*/
|
41 |
+
public function getUsername() {
|
42 |
+
return $this->getRowData()->wp_username;
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @return int
|
47 |
+
*/
|
48 |
+
public function isDeleted() {
|
49 |
+
return $this->getRowData()->deleted_at > 0;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @return stdClass
|
54 |
+
*/
|
55 |
+
public function getRowData() {
|
56 |
+
return $this->oRowData;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @param stdClass $oRowData
|
61 |
+
* @return $this
|
62 |
+
*/
|
63 |
+
public function setRowData( $oRowData ) {
|
64 |
+
$this->oRowData = $oRowData;
|
65 |
+
return $this;
|
66 |
+
}
|
67 |
+
}
|
@@ -6,11 +6,28 @@ if ( class_exists( 'ICWP_WPSF_Query_Base', false ) ) {
|
|
6 |
|
7 |
class ICWP_WPSF_Query_Base extends ICWP_WPSF_Foundation {
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
/**
|
10 |
* @var string
|
11 |
*/
|
12 |
protected $sTable;
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
/**
|
15 |
* @return string
|
16 |
*/
|
@@ -18,6 +35,38 @@ class ICWP_WPSF_Query_Base extends ICWP_WPSF_Foundation {
|
|
18 |
return $this->sTable;
|
19 |
}
|
20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
/**
|
22 |
* @param string $sTable
|
23 |
* @return $this
|
6 |
|
7 |
class ICWP_WPSF_Query_Base extends ICWP_WPSF_Foundation {
|
8 |
|
9 |
+
/**
|
10 |
+
* @var bool
|
11 |
+
*/
|
12 |
+
protected $bResultsAsVo;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var int
|
16 |
+
*/
|
17 |
+
protected $nLimit = 0;
|
18 |
+
|
19 |
/**
|
20 |
* @var string
|
21 |
*/
|
22 |
protected $sTable;
|
23 |
|
24 |
+
/**
|
25 |
+
* @return int
|
26 |
+
*/
|
27 |
+
public function getLimit() {
|
28 |
+
return max( (int)$this->nLimit, 0 );
|
29 |
+
}
|
30 |
+
|
31 |
/**
|
32 |
* @return string
|
33 |
*/
|
35 |
return $this->sTable;
|
36 |
}
|
37 |
|
38 |
+
/**
|
39 |
+
* @return bool
|
40 |
+
*/
|
41 |
+
public function hasLimit() {
|
42 |
+
return $this->getLimit() > 0;
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @return bool
|
47 |
+
*/
|
48 |
+
public function isResultsAsVo() {
|
49 |
+
return $this->bResultsAsVo;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @param int $nLimit
|
54 |
+
* @return $this
|
55 |
+
*/
|
56 |
+
public function setLimit( $nLimit ) {
|
57 |
+
$this->nLimit = $nLimit;
|
58 |
+
return $this;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @param bool $bResultsAsVo
|
63 |
+
* @return $this
|
64 |
+
*/
|
65 |
+
public function setResultsAsVo( $bResultsAsVo ) {
|
66 |
+
$this->bResultsAsVo = $bResultsAsVo;
|
67 |
+
return $this;
|
68 |
+
}
|
69 |
+
|
70 |
/**
|
71 |
* @param string $sTable
|
72 |
* @return $this
|
@@ -8,11 +8,6 @@ require_once( dirname( __FILE__ ).'/base.php' );
|
|
8 |
|
9 |
class ICWP_WPSF_Query_Base_Find extends ICWP_WPSF_Query_Base {
|
10 |
|
11 |
-
/**
|
12 |
-
* @var int
|
13 |
-
*/
|
14 |
-
protected $nLimit = 0;
|
15 |
-
|
16 |
/**
|
17 |
* @var string
|
18 |
*/
|
@@ -35,42 +30,28 @@ class ICWP_WPSF_Query_Base_Find extends ICWP_WPSF_Query_Base {
|
|
35 |
return (string)$this->sTerm;
|
36 |
}
|
37 |
|
38 |
-
/**
|
39 |
-
* @return int
|
40 |
-
*/
|
41 |
-
public function getLimit() {
|
42 |
-
return max( (int)$this->nLimit, 0 );
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* @return bool
|
47 |
-
*/
|
48 |
-
public function hasLimit() {
|
49 |
-
return $this->getLimit() > 0;
|
50 |
-
}
|
51 |
-
|
52 |
/**
|
53 |
* @return array
|
54 |
*/
|
55 |
public function getColumns() {
|
56 |
if ( empty( $this->aColumns ) || !is_array( $this->aColumns ) ) {
|
57 |
-
$this->aColumns =
|
58 |
}
|
59 |
return $this->aColumns;
|
60 |
}
|
61 |
|
62 |
/**
|
63 |
-
* @return
|
64 |
*/
|
65 |
-
|
66 |
-
return
|
67 |
}
|
68 |
|
69 |
/**
|
70 |
* @return bool
|
71 |
*/
|
72 |
-
public function
|
73 |
-
return $this->
|
74 |
}
|
75 |
|
76 |
/**
|
@@ -82,15 +63,6 @@ class ICWP_WPSF_Query_Base_Find extends ICWP_WPSF_Query_Base {
|
|
82 |
return $this;
|
83 |
}
|
84 |
|
85 |
-
/**
|
86 |
-
* @param bool $bResultsAsVo
|
87 |
-
* @return $this
|
88 |
-
*/
|
89 |
-
public function setResultsAsVo( $bResultsAsVo ) {
|
90 |
-
$this->bResultsAsVo = $bResultsAsVo;
|
91 |
-
return $this;
|
92 |
-
}
|
93 |
-
|
94 |
/**
|
95 |
* @param string $sTerm
|
96 |
* @return $this
|
@@ -99,13 +71,4 @@ class ICWP_WPSF_Query_Base_Find extends ICWP_WPSF_Query_Base {
|
|
99 |
$this->sTerm = $sTerm;
|
100 |
return $this;
|
101 |
}
|
102 |
-
|
103 |
-
/**
|
104 |
-
* @param int $nLimit
|
105 |
-
* @return $this
|
106 |
-
*/
|
107 |
-
public function setLimit( $nLimit ) {
|
108 |
-
$this->nLimit = $nLimit;
|
109 |
-
return $this;
|
110 |
-
}
|
111 |
}
|
8 |
|
9 |
class ICWP_WPSF_Query_Base_Find extends ICWP_WPSF_Query_Base {
|
10 |
|
|
|
|
|
|
|
|
|
|
|
11 |
/**
|
12 |
* @var string
|
13 |
*/
|
30 |
return (string)$this->sTerm;
|
31 |
}
|
32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
/**
|
34 |
* @return array
|
35 |
*/
|
36 |
public function getColumns() {
|
37 |
if ( empty( $this->aColumns ) || !is_array( $this->aColumns ) ) {
|
38 |
+
$this->aColumns = $this->getDefaultColumns();
|
39 |
}
|
40 |
return $this->aColumns;
|
41 |
}
|
42 |
|
43 |
/**
|
44 |
+
* @return array
|
45 |
*/
|
46 |
+
protected function getDefaultColumns() {
|
47 |
+
return array( 'wp_username', 'message' );
|
48 |
}
|
49 |
|
50 |
/**
|
51 |
* @return bool
|
52 |
*/
|
53 |
+
public function hasSearchTerm() {
|
54 |
+
return strlen( $this->getTerm() ) > 0;
|
55 |
}
|
56 |
|
57 |
/**
|
63 |
return $this;
|
64 |
}
|
65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
/**
|
67 |
* @param string $sTerm
|
68 |
* @return $this
|
71 |
$this->sTerm = $sTerm;
|
72 |
return $this;
|
73 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
}
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( class_exists( 'ICWP_WPSF_Query_PluginNotes_Create', false ) ) {
|
4 |
+
return;
|
5 |
+
}
|
6 |
+
|
7 |
+
require_once( dirname( __FILE__ ).'/base.php' );
|
8 |
+
|
9 |
+
class ICWP_WPSF_Query_PluginNotes_Create extends ICWP_WPSF_Query_Base {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @param string $sNote
|
13 |
+
* @return bool|int
|
14 |
+
*/
|
15 |
+
public function create( $sNote ) {
|
16 |
+
|
17 |
+
$oUser = $this->loadWpUsers()->getCurrentWpUser();
|
18 |
+
$aNewData = array(
|
19 |
+
'wp_username' => ( $oUser instanceof WP_User ) ? $oUser->user_login : 'unknown',
|
20 |
+
'note' => esc_sql( $sNote ),
|
21 |
+
'created_at' => $this->loadDP()->time(),
|
22 |
+
);
|
23 |
+
$mResult = $this->loadDbProcessor()
|
24 |
+
->insertDataIntoTable( $this->getTable(), $aNewData );
|
25 |
+
return ( $mResult === false ) ? false : $mResult > 0;
|
26 |
+
}
|
27 |
+
}
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( class_exists( 'ICWP_WPSF_Query_PluginNotes_Delete', false ) ) {
|
4 |
+
return;
|
5 |
+
}
|
6 |
+
|
7 |
+
require_once( dirname( __FILE__ ).'/base.php' );
|
8 |
+
|
9 |
+
class ICWP_WPSF_Query_PluginNotes_Delete extends ICWP_WPSF_Query_Base {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @param int $nId
|
13 |
+
* @return bool|int
|
14 |
+
*/
|
15 |
+
public function delete( $nId ) {
|
16 |
+
return $this->loadDbProcessor()
|
17 |
+
->deleteRowsFromTableWhere( $this->getTable(), array( 'id' => (int)$nId ) );
|
18 |
+
}
|
19 |
+
}
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( class_exists( 'ICWP_WPSF_Query_PluginNotes_Find', false ) ) {
|
4 |
+
return;
|
5 |
+
}
|
6 |
+
|
7 |
+
require_once( dirname( __FILE__ ).'/base_find.php' );
|
8 |
+
|
9 |
+
class ICWP_WPSF_Query_PluginNotes_Find extends ICWP_WPSF_Query_Base_Find {
|
10 |
+
|
11 |
+
public function __construct() {
|
12 |
+
$this->init();
|
13 |
+
}
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @return ICWP_WPSF_NoteVO[]|stdClass[]
|
17 |
+
*/
|
18 |
+
public function all() {
|
19 |
+
return $this->query_Search();
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @return ICWP_WPSF_NoteVO[]|stdClass[]
|
24 |
+
*/
|
25 |
+
protected function query_Search() {
|
26 |
+
|
27 |
+
$sQuery = "
|
28 |
+
SELECT *
|
29 |
+
FROM `%s`
|
30 |
+
%s
|
31 |
+
ORDER BY `created_at` DESC
|
32 |
+
%s
|
33 |
+
";
|
34 |
+
$sQuery = sprintf(
|
35 |
+
$sQuery,
|
36 |
+
$this->getTable(),
|
37 |
+
$this->buildWherePhrase(),
|
38 |
+
$this->hasLimit() ? sprintf( 'LIMIT %s', $this->getLimit() ) : ''
|
39 |
+
);
|
40 |
+
|
41 |
+
$aData = $this->loadDbProcessor()
|
42 |
+
->selectCustom( $sQuery, OBJECT_K );
|
43 |
+
|
44 |
+
if ( $this->isResultsAsVo() ) {
|
45 |
+
foreach ( $aData as $nKey => $oResult ) {
|
46 |
+
$aData[ $nKey ] = new ICWP_WPSF_NoteVO( $oResult );
|
47 |
+
}
|
48 |
+
}
|
49 |
+
return $aData;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @return string
|
54 |
+
*/
|
55 |
+
protected function buildWherePhrase() {
|
56 |
+
$sPhrase = '';
|
57 |
+
|
58 |
+
if ( $this->hasSearchTerm() ) {
|
59 |
+
$sTerm = str_replace( '"', '', esc_sql( trim( $this->getTerm() ) ) );
|
60 |
+
|
61 |
+
$sWhereTemplate = '`%s` LIKE "%%%s%%"';
|
62 |
+
$aColumnWheres = $this->getColumns();
|
63 |
+
foreach ( $aColumnWheres as $nKey => $sColumn ) {
|
64 |
+
$aColumnWheres[ $nKey ] = sprintf( $sWhereTemplate, $sColumn, $sTerm );
|
65 |
+
}
|
66 |
+
$sPhrase = sprintf( 'WHERE %s', implode( ' OR ', $aColumnWheres ) );
|
67 |
+
}
|
68 |
+
|
69 |
+
return $sPhrase;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* @return array
|
74 |
+
*/
|
75 |
+
protected function getDefaultColumns() {
|
76 |
+
return array( 'wp_username', 'note' );
|
77 |
+
}
|
78 |
+
|
79 |
+
protected function init() {
|
80 |
+
require_once( dirname( __FILE__ ).'/ICWP_WPSF_NoteVO.php' );
|
81 |
+
}
|
82 |
+
}
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( class_exists( 'ICWP_WPSF_Query_PluginNotes_Retrieve', false ) ) {
|
4 |
+
return;
|
5 |
+
}
|
6 |
+
|
7 |
+
require_once( dirname( __FILE__ ).'/base.php' );
|
8 |
+
|
9 |
+
class ICWP_WPSF_Query_PluginNotes_Retrieve extends ICWP_WPSF_Query_Base {
|
10 |
+
|
11 |
+
public function __construct() {
|
12 |
+
$this->init();
|
13 |
+
}
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @return ICWP_WPSF_NoteVO[]|stdClass[]
|
17 |
+
*/
|
18 |
+
public function all() {
|
19 |
+
return $this->query_retrieve();
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @param int $nId
|
24 |
+
* @return ICWP_WPSF_NoteVO[]|stdClass[]
|
25 |
+
*/
|
26 |
+
public function retrieveById( $nId ) {
|
27 |
+
return $this->query_retrieve( $nId );
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @param int $nId
|
32 |
+
* @return ICWP_WPSF_NoteVO[]|stdClass[]
|
33 |
+
*/
|
34 |
+
protected function query_retrieve( $nId = null ) {
|
35 |
+
$sQuery = "
|
36 |
+
SELECT *
|
37 |
+
FROM `%s`
|
38 |
+
WHERE
|
39 |
+
`deleted_at` = 0
|
40 |
+
%s
|
41 |
+
ORDER BY `created_at` DESC
|
42 |
+
%s
|
43 |
+
";
|
44 |
+
$sQuery = sprintf(
|
45 |
+
$sQuery,
|
46 |
+
$this->getTable(),
|
47 |
+
is_null( $nId ) ? '' : "AND `id` = ".esc_sql( (int)$nId ),
|
48 |
+
$this->hasLimit() ? sprintf( 'LIMIT %s', $this->getLimit() ) : ''
|
49 |
+
);
|
50 |
+
|
51 |
+
$aData = $this->loadDbProcessor()
|
52 |
+
->selectCustom( $sQuery, OBJECT_K );
|
53 |
+
|
54 |
+
if ( $this->isResultsAsVo() ) {
|
55 |
+
foreach ( $aData as $nKey => $oResult ) {
|
56 |
+
$aData[ $nKey ] = new ICWP_WPSF_NoteVO( $oResult );
|
57 |
+
}
|
58 |
+
}
|
59 |
+
return $aData;
|
60 |
+
}
|
61 |
+
|
62 |
+
protected function init() {
|
63 |
+
require_once( dirname( __FILE__ ).'/ICWP_WPSF_NoteVO.php' );
|
64 |
+
}
|
65 |
+
}
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div id="SectionAdminNotes" class="insights_widget card w-100 p-0">
|
2 |
+
<div class="card-header">
|
3 |
+
<h5 class="card-title">Administrator Notes</h5>
|
4 |
+
<h6 class="card-subtitle mb-2 text-muted">All your admin notes</h6>
|
5 |
+
</div>
|
6 |
+
<div class="card-body overflow_container">
|
7 |
+
|
8 |
+
<div id="AdminNotesContainer" class="overflow_inner p-0">
|
9 |
+
{% include '/wpadmin_pages/insights/admin_notes_table.twig' %}
|
10 |
+
</div>
|
11 |
+
|
12 |
+
</div>
|
13 |
+
<div class="card-footer p-0" style="margin-bottom: -1px;">
|
14 |
+
<form class="form-inline" id="NewAdminNote" action="#" method="post">
|
15 |
+
{% for name,val in ajax.admin_note_new %}
|
16 |
+
<input type="hidden" name="{{ name }}" value="{{ val }}" />
|
17 |
+
{% endfor %}
|
18 |
+
<label class="sr-only" for="AdminNote">Note</label>
|
19 |
+
<div class="input-group w-100">
|
20 |
+
<div class="input-group-prepend">
|
21 |
+
<div class="input-group-text" style="border-radius: 0">New Note:</div>
|
22 |
+
</div>
|
23 |
+
<textarea class="form-control" id="AdminNote" name="admin_note" rows="2"
|
24 |
+
placeholder="{% if flags.can_notes %}Enter new note here{% else %}Sorry, Admin Notes is a Pro-only feature{% endif %}"
|
25 |
+
></textarea>
|
26 |
+
<div class="input-group-append">
|
27 |
+
<button type="submit" class="btn btn-info" style="border-radius: 0;" name="subbutt"
|
28 |
+
{% if not flags.can_notes %}disabled="disabled"{% endif %}
|
29 |
+
>Add Note</button>
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
+
</form>
|
33 |
+
</div>
|
34 |
+
</div>
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% if flags.has_notes %}
|
2 |
+
<table class="table table-hover mb-0">
|
3 |
+
<thead><tr>
|
4 |
+
<th>Note</th>
|
5 |
+
<th>User</th>
|
6 |
+
<th>Date</th>
|
7 |
+
</tr></thead>
|
8 |
+
{% for note in vars.insight_notes %}
|
9 |
+
<tr class="message_row">
|
10 |
+
<td>{{ note.note }}</td>
|
11 |
+
<td>{{ note.wp_username }}</td>
|
12 |
+
<td>{{ note.created_at }}</td>
|
13 |
+
</tr>
|
14 |
+
{% endfor %}
|
15 |
+
</table>
|
16 |
+
{% else %}
|
17 |
+
<div class="alert alert-info">There are no admin notes.</div>
|
18 |
+
{% endif %}
|
@@ -7,10 +7,10 @@
|
|
7 |
|
8 |
{% block body_main %}
|
9 |
<div class="row">
|
10 |
-
<div class="col-
|
11 |
{% include '/wpadmin_pages/insights/title.twig' %}
|
12 |
</div>
|
13 |
-
<div class="col-
|
14 |
{% include '/wpadmin_pages/insights/stats.twig' %}
|
15 |
</div>
|
16 |
</div>
|
@@ -18,13 +18,20 @@
|
|
18 |
<div class="col-lg-7">
|
19 |
{% include '/wpadmin_pages/insights/notices.twig' %}
|
20 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
<div class="col-lg-5">
|
22 |
{% include '/wpadmin_pages/insights/recent_events.twig' %}
|
23 |
</div>
|
24 |
</div>
|
25 |
<div class="row">
|
26 |
<div class="col">
|
27 |
-
{% include '/wpadmin_pages/insights/audit_trail.twig' %}
|
28 |
</div>
|
29 |
</div>
|
30 |
{% endblock %}
|
@@ -60,22 +67,23 @@
|
|
60 |
.overflow_inner dl {
|
61 |
margin-bottom: 1px;
|
62 |
}
|
63 |
-
|
64 |
.title_row th,
|
65 |
.title_row td {
|
66 |
background-color: #fbfbfb;
|
67 |
}
|
68 |
-
|
69 |
.message_row th,
|
70 |
.message_row td {
|
71 |
padding-bottom: 5px;
|
72 |
border-top: 1px solid #e9edf1; /** make bootstrap border lighter */
|
73 |
}
|
74 |
-
|
75 |
.icon-sign {
|
76 |
font-size: 14px;
|
77 |
}
|
78 |
|
|
|
|
|
|
|
|
|
79 |
#SectionAuditTrail table {
|
80 |
font-size: 12px;
|
81 |
}
|
@@ -88,7 +96,7 @@
|
|
88 |
#odp-BodyFoot {
|
89 |
position: sticky;
|
90 |
bottom: 0;
|
91 |
-
z-index:
|
92 |
margin-top: 30px;
|
93 |
}
|
94 |
#SectionStats {
|
7 |
|
8 |
{% block body_main %}
|
9 |
<div class="row">
|
10 |
+
<div class="col-6">
|
11 |
{% include '/wpadmin_pages/insights/title.twig' %}
|
12 |
</div>
|
13 |
+
<div class="col-6">
|
14 |
{% include '/wpadmin_pages/insights/stats.twig' %}
|
15 |
</div>
|
16 |
</div>
|
18 |
<div class="col-lg-7">
|
19 |
{% include '/wpadmin_pages/insights/notices.twig' %}
|
20 |
</div>
|
21 |
+
<div class="col-lg-5">
|
22 |
+
{% include '/wpadmin_pages/insights/admin_notes.twig' %}
|
23 |
+
</div>
|
24 |
+
</div>
|
25 |
+
<div class="row">
|
26 |
+
<div class="col-lg-7">
|
27 |
+
{% include '/wpadmin_pages/insights/audit_trail.twig' %}
|
28 |
+
</div>
|
29 |
<div class="col-lg-5">
|
30 |
{% include '/wpadmin_pages/insights/recent_events.twig' %}
|
31 |
</div>
|
32 |
</div>
|
33 |
<div class="row">
|
34 |
<div class="col">
|
|
|
35 |
</div>
|
36 |
</div>
|
37 |
{% endblock %}
|
67 |
.overflow_inner dl {
|
68 |
margin-bottom: 1px;
|
69 |
}
|
|
|
70 |
.title_row th,
|
71 |
.title_row td {
|
72 |
background-color: #fbfbfb;
|
73 |
}
|
|
|
74 |
.message_row th,
|
75 |
.message_row td {
|
76 |
padding-bottom: 5px;
|
77 |
border-top: 1px solid #e9edf1; /** make bootstrap border lighter */
|
78 |
}
|
|
|
79 |
.icon-sign {
|
80 |
font-size: 14px;
|
81 |
}
|
82 |
|
83 |
+
#NewAdminNote textarea {
|
84 |
+
height: 64px;
|
85 |
+
}
|
86 |
+
|
87 |
#SectionAuditTrail table {
|
88 |
font-size: 12px;
|
89 |
}
|
96 |
#odp-BodyFoot {
|
97 |
position: sticky;
|
98 |
bottom: 0;
|
99 |
+
z-index: 2;
|
100 |
margin-top: 30px;
|
101 |
}
|
102 |
#SectionStats {
|
@@ -1,6 +1,6 @@
|
|
1 |
<div class="row" id="SectionStats">
|
2 |
{% for stat in vars.insight_stats %}
|
3 |
-
<div class="col-
|
4 |
<div class="stat card"
|
5 |
{% if stat.tooltip is defined %}
|
6 |
title="{{ stat.tooltip }}"
|
1 |
<div class="row" id="SectionStats">
|
2 |
{% for stat in vars.insight_stats %}
|
3 |
+
<div class="col-md-3">
|
4 |
<div class="stat card"
|
5 |
{% if stat.tooltip is defined %}
|
6 |
title="{{ stat.tooltip }}"
|