Version Description
Download this release
Release Info
Developer | maxchirkov |
Plugin | Simple Login Log |
Version | 0.9.3 |
Comparing to | |
See all releases |
Code changes from version 0.9.2 to 0.9.3
- languages/simple-login-log.pot +46 -34
- readme.txt +14 -7
- simple-login-log.php +182 -188
- uninstall.php +16 -0
languages/simple-login-log.pot
CHANGED
@@ -1,134 +1,146 @@
|
|
1 |
-
# Copyright (C)
|
2 |
# This file is distributed under the same license as the Simple Login Log package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
-
"Project-Id-Version: Simple Login Log 0.
|
6 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/simple-login-log\n"
|
7 |
-
"POT-Creation-Date:
|
8 |
"MIME-Version: 1.0\n"
|
9 |
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
"Content-Transfer-Encoding: 8bit\n"
|
11 |
-
"PO-Revision-Date:
|
12 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
|
15 |
-
#: simple-login-log.php:
|
16 |
msgid "Successful"
|
17 |
msgstr ""
|
18 |
|
19 |
-
#: simple-login-log.php:
|
20 |
msgid "Failed"
|
21 |
msgstr ""
|
22 |
|
23 |
-
#: simple-login-log.php:
|
24 |
msgid "Login"
|
25 |
msgstr ""
|
26 |
|
27 |
-
#: simple-login-log.php:
|
28 |
msgid "User Agent"
|
29 |
msgstr ""
|
30 |
|
31 |
-
#: simple-login-log.php:
|
32 |
msgid "Login Redirect"
|
33 |
msgstr ""
|
34 |
|
35 |
-
#: simple-login-log.php:
|
36 |
msgid "#"
|
37 |
msgstr ""
|
38 |
|
39 |
-
#: simple-login-log.php:
|
40 |
msgid "User ID"
|
41 |
msgstr ""
|
42 |
|
43 |
-
#: simple-login-log.php:
|
44 |
msgid "Username"
|
45 |
msgstr ""
|
46 |
|
47 |
-
#: simple-login-log.php:
|
|
|
|
|
|
|
|
|
48 |
msgid "Name"
|
49 |
msgstr ""
|
50 |
|
51 |
-
#: simple-login-log.php:
|
52 |
msgid "Time"
|
53 |
msgstr ""
|
54 |
|
55 |
-
#: simple-login-log.php:
|
56 |
msgid "IP Address"
|
57 |
msgstr ""
|
58 |
|
59 |
-
#: simple-login-log.php:
|
60 |
msgid "Login Result"
|
61 |
msgstr ""
|
62 |
|
63 |
-
#: simple-login-log.php:
|
64 |
msgid "Data"
|
65 |
msgstr ""
|
66 |
|
67 |
-
#: simple-login-log.php:
|
68 |
msgid "Records"
|
69 |
msgstr ""
|
70 |
|
71 |
-
#. #-#-#-#-# plugin.pot (Simple Login Log 0.
|
72 |
#. Plugin Name of the plugin/theme
|
73 |
-
#: simple-login-log.php:
|
74 |
msgid "Simple Login Log"
|
75 |
msgstr ""
|
76 |
|
77 |
-
#: simple-login-log.php:
|
78 |
msgid "Truncate Log Entries"
|
79 |
msgstr ""
|
80 |
|
81 |
-
#: simple-login-log.php:
|
82 |
msgid "Log Failed Attempts"
|
83 |
msgstr ""
|
84 |
|
85 |
-
#: simple-login-log.php:
|
86 |
msgid "Login Log"
|
87 |
msgstr ""
|
88 |
|
89 |
-
#: simple-login-log.php:
|
|
|
|
|
|
|
|
|
90 |
msgid "Leave empty or enter 0 if you don't want the log to be truncated."
|
91 |
msgstr ""
|
92 |
|
93 |
-
#: simple-login-log.php:
|
94 |
msgid ""
|
95 |
"Logs failed attempts where user name and password are entered. Will not log "
|
96 |
"if at least one of the mentioned fields is empty."
|
97 |
msgstr ""
|
98 |
|
99 |
-
#: simple-login-log.php:
|
100 |
msgid "Username:"
|
101 |
msgstr ""
|
102 |
|
103 |
-
#: simple-login-log.php:
|
104 |
msgid "Filter User"
|
105 |
msgstr ""
|
106 |
|
107 |
-
#: simple-login-log.php:
|
108 |
msgid "Export Log to CSV"
|
109 |
msgstr ""
|
110 |
|
111 |
-
#: simple-login-log.php:
|
112 |
msgid "Export Current Results to CSV"
|
113 |
msgstr ""
|
114 |
|
115 |
-
#: simple-login-log.php:
|
116 |
msgid "View All"
|
117 |
msgstr ""
|
118 |
|
119 |
-
#: simple-login-log.php:
|
120 |
msgid "Filter"
|
121 |
msgstr ""
|
122 |
|
123 |
-
#: simple-login-log.php:
|
124 |
msgid "Filter log by this name"
|
125 |
msgstr ""
|
126 |
|
127 |
-
#: simple-login-log.php:
|
|
|
|
|
|
|
|
|
128 |
msgid "Login Results"
|
129 |
msgstr ""
|
130 |
|
131 |
-
#: simple-login-log.php:
|
132 |
msgid "All"
|
133 |
msgstr ""
|
134 |
|
1 |
+
# Copyright (C) 2012 Simple Login Log
|
2 |
# This file is distributed under the same license as the Simple Login Log package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
+
"Project-Id-Version: Simple Login Log 0.9.3\n"
|
6 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/simple-login-log\n"
|
7 |
+
"POT-Creation-Date: 2012-05-22 19:12:22+00:00\n"
|
8 |
"MIME-Version: 1.0\n"
|
9 |
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
"Content-Transfer-Encoding: 8bit\n"
|
11 |
+
"PO-Revision-Date: 2012-MO-DA HO:MI+ZONE\n"
|
12 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
|
15 |
+
#: simple-login-log.php:65 simple-login-log.php:820
|
16 |
msgid "Successful"
|
17 |
msgstr ""
|
18 |
|
19 |
+
#: simple-login-log.php:66 simple-login-log.php:821
|
20 |
msgid "Failed"
|
21 |
msgstr ""
|
22 |
|
23 |
+
#: simple-login-log.php:67
|
24 |
msgid "Login"
|
25 |
msgstr ""
|
26 |
|
27 |
+
#: simple-login-log.php:68
|
28 |
msgid "User Agent"
|
29 |
msgstr ""
|
30 |
|
31 |
+
#: simple-login-log.php:69
|
32 |
msgid "Login Redirect"
|
33 |
msgstr ""
|
34 |
|
35 |
+
#: simple-login-log.php:70
|
36 |
msgid "#"
|
37 |
msgstr ""
|
38 |
|
39 |
+
#: simple-login-log.php:71
|
40 |
msgid "User ID"
|
41 |
msgstr ""
|
42 |
|
43 |
+
#: simple-login-log.php:72
|
44 |
msgid "Username"
|
45 |
msgstr ""
|
46 |
|
47 |
+
#: simple-login-log.php:73
|
48 |
+
msgid "User Role"
|
49 |
+
msgstr ""
|
50 |
+
|
51 |
+
#: simple-login-log.php:74
|
52 |
msgid "Name"
|
53 |
msgstr ""
|
54 |
|
55 |
+
#: simple-login-log.php:75
|
56 |
msgid "Time"
|
57 |
msgstr ""
|
58 |
|
59 |
+
#: simple-login-log.php:76
|
60 |
msgid "IP Address"
|
61 |
msgstr ""
|
62 |
|
63 |
+
#: simple-login-log.php:77
|
64 |
msgid "Login Result"
|
65 |
msgstr ""
|
66 |
|
67 |
+
#: simple-login-log.php:78
|
68 |
msgid "Data"
|
69 |
msgstr ""
|
70 |
|
71 |
+
#: simple-login-log.php:128
|
72 |
msgid "Records"
|
73 |
msgstr ""
|
74 |
|
75 |
+
#. #-#-#-#-# plugin.pot (Simple Login Log 0.9.3) #-#-#-#-#
|
76 |
#. Plugin Name of the plugin/theme
|
77 |
+
#: simple-login-log.php:339 simple-login-log.php:349
|
78 |
msgid "Simple Login Log"
|
79 |
msgstr ""
|
80 |
|
81 |
+
#: simple-login-log.php:340
|
82 |
msgid "Truncate Log Entries"
|
83 |
msgstr ""
|
84 |
|
85 |
+
#: simple-login-log.php:341
|
86 |
msgid "Log Failed Attempts"
|
87 |
msgstr ""
|
88 |
|
89 |
+
#: simple-login-log.php:349 simple-login-log.php:501
|
90 |
msgid "Login Log"
|
91 |
msgstr ""
|
92 |
|
93 |
+
#: simple-login-log.php:362
|
94 |
+
msgid "days and older."
|
95 |
+
msgstr ""
|
96 |
+
|
97 |
+
#: simple-login-log.php:364
|
98 |
msgid "Leave empty or enter 0 if you don't want the log to be truncated."
|
99 |
msgstr ""
|
100 |
|
101 |
+
#: simple-login-log.php:377
|
102 |
msgid ""
|
103 |
"Logs failed attempts where user name and password are entered. Will not log "
|
104 |
"if at least one of the mentioned fields is empty."
|
105 |
msgstr ""
|
106 |
|
107 |
+
#: simple-login-log.php:511
|
108 |
msgid "Username:"
|
109 |
msgstr ""
|
110 |
|
111 |
+
#: simple-login-log.php:511
|
112 |
msgid "Filter User"
|
113 |
msgstr ""
|
114 |
|
115 |
+
#: simple-login-log.php:536
|
116 |
msgid "Export Log to CSV"
|
117 |
msgstr ""
|
118 |
|
119 |
+
#: simple-login-log.php:545
|
120 |
msgid "Export Current Results to CSV"
|
121 |
msgstr ""
|
122 |
|
123 |
+
#: simple-login-log.php:576
|
124 |
msgid "View All"
|
125 |
msgstr ""
|
126 |
|
127 |
+
#: simple-login-log.php:577
|
128 |
msgid "Filter"
|
129 |
msgstr ""
|
130 |
|
131 |
+
#: simple-login-log.php:678
|
132 |
msgid "Filter log by this name"
|
133 |
msgstr ""
|
134 |
|
135 |
+
#: simple-login-log.php:692
|
136 |
+
msgid "Filter log by User Role"
|
137 |
+
msgstr ""
|
138 |
+
|
139 |
+
#: simple-login-log.php:819
|
140 |
msgid "Login Results"
|
141 |
msgstr ""
|
142 |
|
143 |
+
#: simple-login-log.php:819
|
144 |
msgid "All"
|
145 |
msgstr ""
|
146 |
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: http://www.ibsteam.net/donate
|
|
4 |
Tags: login, log, users
|
5 |
Requires at least: 3.0
|
6 |
Tested up to: 3.3.2
|
7 |
-
Stable tag: 0.9.
|
8 |
|
9 |
This plugin keeps a log of WordPress user logins. Offers user and date filtering, and export features.
|
10 |
|
@@ -14,7 +14,7 @@ Simple log of user logins. Tracks username, time of login, IP address and browse
|
|
14 |
|
15 |
[Demo Video](http://screenr.com/kfEs "Demo Video")
|
16 |
|
17 |
-
**Features include:**
|
18 |
|
19 |
1. ability to filter by username, successful/failed logins, month and year;
|
20 |
2. export into CSV file;
|
@@ -28,10 +28,10 @@ Simple log of user logins. Tracks username, time of login, IP address and browse
|
|
28 |
== Installation ==
|
29 |
|
30 |
1. Install and activate like any other basic plugin.
|
31 |
-
2. If you wish to set log trancation or opt-in to record failed login
|
32 |
3. To view login log, go to Users => Login Log. You can export the log to CSV file form the same page.
|
33 |
|
34 |
-
Screen Options are available at the top of the Login Log page. Click on the *Secreen Options* tab to expand the options section. You'll be able to change the number of results
|
35 |
|
36 |
== Screenshots ==
|
37 |
|
@@ -40,6 +40,13 @@ Screen Options are available at the top of the Login Log page. Click on the *Sec
|
|
40 |
|
41 |
== Changelog ==
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
**Version 0.9.2**
|
44 |
|
45 |
- Daily cron job with log truncation didn't work.
|
@@ -63,7 +70,7 @@ Screen Options are available at the top of the Login Log page. Click on the *Sec
|
|
63 |
|
64 |
**Version 0.5**
|
65 |
|
66 |
-
- Bug fix: in_array() warning for hidden columns not returning an array.
|
67 |
|
68 |
**Version 0.4**
|
69 |
|
@@ -90,7 +97,7 @@ For example, we can use this filter to link IP addresses to a geo-location servi
|
|
90 |
<?php
|
91 |
add_filter( 'sll-output-data', 'link_location_by_ip' );
|
92 |
function link_location_by_ip($item){
|
93 |
-
|
94 |
//$item is a single row for columns with their values
|
95 |
|
96 |
$item['ip'] = sprintf('<a target="_blank" href="http://infosniper.net/index.php?ip_address=%1$s&map_source=3&two_maps=1&overview_map=1&lang=1&map_type=1&zoom_level=11">%1$s</a>', $item['ip']);
|
@@ -101,4 +108,4 @@ function link_location_by_ip($item){
|
|
101 |
|
102 |
= Translation =
|
103 |
|
104 |
-
Currently there are no
|
4 |
Tags: login, log, users
|
5 |
Requires at least: 3.0
|
6 |
Tested up to: 3.3.2
|
7 |
+
Stable tag: 0.9.3
|
8 |
|
9 |
This plugin keeps a log of WordPress user logins. Offers user and date filtering, and export features.
|
10 |
|
14 |
|
15 |
[Demo Video](http://screenr.com/kfEs "Demo Video")
|
16 |
|
17 |
+
**Features include:**
|
18 |
|
19 |
1. ability to filter by username, successful/failed logins, month and year;
|
20 |
2. export into CSV file;
|
28 |
== Installation ==
|
29 |
|
30 |
1. Install and activate like any other basic plugin.
|
31 |
+
2. If you wish to set log trancation or opt-in to record failed login attempts, go to Settings => General. Scroll down to Simple Login Log.
|
32 |
3. To view login log, go to Users => Login Log. You can export the log to CSV file form the same page.
|
33 |
|
34 |
+
Screen Options are available at the top of the Login Log page. Click on the *Secreen Options* tab to expand the options section. You'll be able to change the number of results per page as well as hide/display table columns.
|
35 |
|
36 |
== Screenshots ==
|
37 |
|
40 |
|
41 |
== Changelog ==
|
42 |
|
43 |
+
**Version 0.9.3**
|
44 |
+
|
45 |
+
- Improvement: search by partial user name as well as partial IP address per [Commeuneimage's recommendation](http://wordpress.org/support/topic/plugin-simple-login-log-small-enhancement-suggested-on-search-feature).
|
46 |
+
- Updated POT file.
|
47 |
+
- Added Russian and Ukrainian Translation.
|
48 |
+
- Added uninstall.php to all plugin's data from the database on plugin deletion.
|
49 |
+
|
50 |
**Version 0.9.2**
|
51 |
|
52 |
- Daily cron job with log truncation didn't work.
|
70 |
|
71 |
**Version 0.5**
|
72 |
|
73 |
+
- Bug fix: in_array() warning for hidden columns not returning an array.
|
74 |
|
75 |
**Version 0.4**
|
76 |
|
97 |
<?php
|
98 |
add_filter( 'sll-output-data', 'link_location_by_ip' );
|
99 |
function link_location_by_ip($item){
|
100 |
+
|
101 |
//$item is a single row for columns with their values
|
102 |
|
103 |
$item['ip'] = sprintf('<a target="_blank" href="http://infosniper.net/index.php?ip_address=%1$s&map_source=3&two_maps=1&overview_map=1&lang=1&map_type=1&zoom_level=11">%1$s</a>', $item['ip']);
|
108 |
|
109 |
= Translation =
|
110 |
|
111 |
+
Currently there are no translations available. If you would like to contribute, the POT file is available in the *languages* folder. Translation file name convention is *sll-{locale}.mo*, where {locale} is the locale of your language. Fore example, Russian file name would be *sll-ru_RU.po*.
|
simple-login-log.php
CHANGED
@@ -4,24 +4,24 @@
|
|
4 |
Plugin URI: http://simplerealtytheme.com
|
5 |
Description: This plugin keeps a log of WordPress user logins. Offers user filtering and export features.
|
6 |
Author: Max Chirkov
|
7 |
-
Version: 0.9.
|
8 |
Author URI: http://SimpleRealtyTheme.com
|
9 |
*/
|
10 |
|
11 |
//TODO: add cleanup method on uninstall
|
12 |
|
13 |
if( !class_exists( 'SimpleLoginLog' ) )
|
14 |
-
{
|
15 |
class SimpleLoginLog {
|
16 |
private $db_ver = "1.2";
|
17 |
public $table = 'simple_login_log';
|
18 |
private $log_duration = null; //days
|
19 |
private $opt_name = 'simple_login_log';
|
20 |
private $opt = false;
|
21 |
-
private $login_success = 1;
|
22 |
public $data_labels = array();
|
23 |
|
24 |
-
|
25 |
function __construct()
|
26 |
{
|
27 |
global $wpdb;
|
@@ -31,13 +31,13 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
31 |
//Get plugin's DB version
|
32 |
$this->installed_ver = get_option( "sll_db_ver" );
|
33 |
|
34 |
-
//Check if download was initiated
|
35 |
$download = @esc_attr( $_GET['download-login-log'] );
|
36 |
if($download)
|
37 |
{
|
38 |
$where = ( isset($_GET['where']) ) ? $_GET['where'] : false;
|
39 |
$this->export_to_CSV($where);
|
40 |
-
}
|
41 |
|
42 |
|
43 |
add_action( 'admin_menu', array(&$this, 'sll_admin_menu') );
|
@@ -46,10 +46,10 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
46 |
|
47 |
//check if db needs to be upgraded after plugin update was completed
|
48 |
add_action('plugins_loaded', array(&$this, 'update_db_check') );
|
49 |
-
|
50 |
//Init login actions
|
51 |
-
add_action( 'init', array(&$this, 'init_login_actions') );
|
52 |
-
|
53 |
//Style the log table
|
54 |
add_action( 'admin_head', array(&$this, 'admin_header') );
|
55 |
|
@@ -58,7 +58,7 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
58 |
add_action('truncate_sll', array(&$this, 'cron') );
|
59 |
|
60 |
//Load Locale
|
61 |
-
add_action('
|
62 |
|
63 |
//For translation purposes
|
64 |
$this->data_labels = array(
|
@@ -85,18 +85,13 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
85 |
|
86 |
|
87 |
function load_locale()
|
88 |
-
{
|
89 |
-
|
90 |
-
if( empty( $locale ) )
|
91 |
-
$locale = 'en_US';
|
92 |
-
|
93 |
-
$mofile = dirname( __FILE__ )."/languages/sll-{$locale}.mo";
|
94 |
-
load_textdomain( 'sll', $mofile );
|
95 |
}
|
96 |
|
97 |
|
98 |
function cron()
|
99 |
-
{
|
100 |
SimpleLoginLog::truncate_log();
|
101 |
}
|
102 |
|
@@ -107,7 +102,7 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
107 |
//execute only on login_log page, othewise return null
|
108 |
$page = ( isset($_GET['page']) ) ? esc_attr($_GET['page']) : false;
|
109 |
if( 'login_log' != $page )
|
110 |
-
return;
|
111 |
|
112 |
$current_screen = get_current_screen();
|
113 |
|
@@ -119,17 +114,17 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
119 |
if( isset($_REQUEST['wp_screen_options']) && isset($_REQUEST['wp_screen_options']['value']) )
|
120 |
{
|
121 |
update_option( $per_page_option, esc_html($_REQUEST['wp_screen_options']['value']) );
|
122 |
-
}
|
123 |
|
124 |
//prepare options for display
|
125 |
|
126 |
//if per page option is not set, use default
|
127 |
-
$per_page_val = get_option($per_page_option, 20);
|
128 |
$args = array('label' => __('Records', 'sll'), 'default' => $per_page_val );
|
129 |
|
130 |
//display options
|
131 |
-
add_screen_option($per_page_field, $args);
|
132 |
-
$_per_page = get_option('users_page_login_log_per_page');
|
133 |
|
134 |
//needs to be initialized early enough to pre-fill screen options section in the upper (hidden) area.
|
135 |
$this->log_table = new SLL_List_Table;
|
@@ -141,10 +136,10 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
141 |
//condition to check if "log failed attemts" option is selected
|
142 |
|
143 |
//Action on successfull login
|
144 |
-
add_action( 'wp_login', array(&$this, 'login_success') );
|
145 |
|
146 |
-
//Action on failed login
|
147 |
-
if( isset($this->opt['failed_attempts']) ){
|
148 |
add_action( 'wp_login_failed', array(&$this, 'login_failed') );
|
149 |
}
|
150 |
|
@@ -166,19 +161,19 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
166 |
|
167 |
|
168 |
function init_scheduled_events()
|
169 |
-
{
|
170 |
|
171 |
$log_duration = get_option('simple_login_log');
|
172 |
|
173 |
-
if ( $log_duration && !wp_next_scheduled( 'truncate_sll' ) )
|
174 |
-
{
|
175 |
$start = time();
|
176 |
wp_schedule_event($start, 'daily', 'truncate_sll');
|
177 |
}elseif( !$log_duration || 0 == $log_duration)
|
178 |
{
|
179 |
$timestamp = wp_next_scheduled( 'truncate_sll' );
|
180 |
(!$timestamp) ? false : wp_unschedule_event($timestamp, 'truncate_sll');
|
181 |
-
|
182 |
}
|
183 |
}
|
184 |
|
@@ -188,7 +183,7 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
188 |
|
189 |
//clean up old cron jobs that no longer exist
|
190 |
wp_clear_scheduled_hook('truncate_log');
|
191 |
-
wp_clear_scheduled_hook('SimpleLoginLog::truncate_log');
|
192 |
}
|
193 |
|
194 |
|
@@ -198,14 +193,14 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
198 |
|
199 |
$opt = get_option('simple_login_log');
|
200 |
$log_duration = (int)$opt['log_duration'];
|
201 |
-
|
202 |
$table = $wpdb->prefix . 'simple_login_log';
|
203 |
|
204 |
-
if( 0 < $log_duration ){
|
205 |
$sql = $wpdb->prepare( "DELETE FROM {$table} WHERE time < DATE_SUB(CURDATE(),INTERVAL %d DAY)", $log_duration);
|
206 |
-
$wpdb->query($sql);
|
207 |
}
|
208 |
-
|
209 |
}
|
210 |
|
211 |
|
@@ -213,20 +208,20 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
213 |
* Runs via plugin activation hook & creates a database
|
214 |
*/
|
215 |
function install()
|
216 |
-
{
|
217 |
global $wpdb;
|
218 |
|
219 |
if( $this->installed_ver != $this->db_ver )
|
220 |
{
|
221 |
//if table does't exist, create a new one
|
222 |
if( !$wpdb->get_row("SHOW TABLES LIKE '{$this->table}'") ){
|
223 |
-
$sql = "CREATE TABLE " . $this->table . "
|
224 |
(
|
225 |
id INT( 11 ) NOT NULL AUTO_INCREMENT ,
|
226 |
uid INT( 11 ) NOT NULL ,
|
227 |
user_login VARCHAR( 60 ) NOT NULL ,
|
228 |
user_role VARCHAR( 30 ) NOT NULL ,
|
229 |
-
time DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL ,
|
230 |
ip VARCHAR( 100 ) NOT NULL ,
|
231 |
login_result VARCHAR (1) ,
|
232 |
data LONGTEXT NOT NULL ,
|
@@ -240,11 +235,11 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
240 |
update_option( "sll_db_ver", $this->db_ver );
|
241 |
}
|
242 |
}
|
243 |
-
|
244 |
-
|
245 |
}
|
246 |
|
247 |
-
|
248 |
/**
|
249 |
* Checks if the installed database version is the same as the db version of the current plugin
|
250 |
* calles the version specific function if upgrade is required
|
@@ -271,7 +266,7 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
271 |
*/
|
272 |
function db_update_1_1()
|
273 |
{
|
274 |
-
|
275 |
/* this version adds a new field "login_result"
|
276 |
* check if this field exists
|
277 |
*/
|
@@ -284,21 +279,21 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
284 |
$this->install();
|
285 |
return;
|
286 |
}
|
287 |
-
|
288 |
$field_names = array_keys( $fields );
|
289 |
-
|
290 |
if( !array_search('login_result', $field_names) )
|
291 |
-
{
|
292 |
//add the new field since it doesn't exist
|
293 |
$sql = "ALTER TABLE {$this->table} ADD COLUMN login_result varchar(1) NOT NULL AFTER ip, ADD INDEX (login_result);";
|
294 |
$insert = $wpdb->query( $sql );
|
295 |
-
|
296 |
//update version record if it has been updated
|
297 |
if( false !== $insert )
|
298 |
update_option( "sll_db_ver", $this->db_ver );
|
299 |
|
300 |
}
|
301 |
-
|
302 |
}
|
303 |
|
304 |
|
@@ -316,30 +311,30 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
316 |
$this->install();
|
317 |
return;
|
318 |
}
|
319 |
-
|
320 |
$field_names = array_keys( $fields );
|
321 |
-
|
322 |
if( !array_search('user_role', $field_names) )
|
323 |
-
{
|
324 |
//add the new field since it doesn't exist
|
325 |
$sql = "ALTER TABLE {$this->table} ADD COLUMN user_role varchar(30) NOT NULL AFTER user_login;";
|
326 |
$insert = $wpdb->query( $sql );
|
327 |
-
|
328 |
//update version record if it has been updated
|
329 |
if( false !== $insert )
|
330 |
update_option( "sll_db_ver", $this->db_ver );
|
331 |
-
|
332 |
}
|
333 |
}
|
334 |
-
|
335 |
|
336 |
//Initializing Settings
|
337 |
function settings_api_init()
|
338 |
{
|
339 |
-
add_settings_section('simple_login_log', __('Simple Login Log', 'sll'), array(&$this, 'sll_settings'), 'general');
|
340 |
add_settings_field('field_log_duration', __('Truncate Log Entries', 'sll'), array(&$this, 'field_log_duration'), 'general', 'simple_login_log');
|
341 |
add_settings_field('field_log_failed_attempts', __('Log Failed Attempts', 'sll'), array(&$this, 'field_log_failed_attempts'), 'general', 'simple_login_log');
|
342 |
-
register_setting( 'general', 'simple_login_log' );
|
343 |
|
344 |
}
|
345 |
|
@@ -351,21 +346,21 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
351 |
|
352 |
|
353 |
function sll_settings()
|
354 |
-
{
|
355 |
//content that goes before the fields output
|
356 |
}
|
357 |
|
358 |
|
359 |
function field_log_duration()
|
360 |
{
|
361 |
-
$duration = (null !== $this->opt['log_duration']) ? $this->opt['log_duration'] : $this->log_duration;
|
362 |
-
$output = '<input type="text" value="' . $duration . '" name="simple_login_log[log_duration]" size="10" class="code" /> days and older.';
|
363 |
echo $output;
|
364 |
echo "<p>" . __("Leave empty or enter 0 if you don't want the log to be truncated.", 'sll') . "</p>";
|
365 |
|
366 |
//since we're on the General Settings page - update cron schedule if settings has been updated
|
367 |
-
if( isset($_REQUEST['settings-updated']) ){
|
368 |
-
wp_clear_scheduled_hook('truncate_sll');
|
369 |
//$this->init_scheduled_events();
|
370 |
}
|
371 |
}
|
@@ -382,7 +377,7 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
382 |
{
|
383 |
$page = ( isset($_GET['page']) ) ? esc_attr($_GET['page']) : false;
|
384 |
if( 'login_log' != $page )
|
385 |
-
return;
|
386 |
|
387 |
echo '<style type="text/css">';
|
388 |
echo '.wp-list-table .column-id { width: 5%; }';
|
@@ -400,15 +395,15 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
400 |
//Catch messages on successful login
|
401 |
function login_action($user_login)
|
402 |
{
|
403 |
-
|
404 |
$userdata = get_user_by('login', $user_login);
|
405 |
|
406 |
$uid = ($userdata && $userdata->ID) ? $userdata->ID : 0;
|
407 |
-
|
408 |
$data[$this->data_labels['Login']] = ( 1 == $this->login_success ) ? $this->data_labels['Successful'] : $this->data_labels['Failed'];
|
409 |
-
if ( isset( $_REQUEST['redirect_to'] ) ) { $data[$this->data_labels['Login Redirect']] = $_REQUEST['redirect_to']; }
|
410 |
$data[$this->data_labels['User Agent']] = $_SERVER['HTTP_USER_AGENT'];
|
411 |
-
|
412 |
$serialized_data = serialize($data);
|
413 |
|
414 |
//get user role
|
@@ -419,22 +414,22 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
419 |
$user_role = implode(', ', $user->roles);
|
420 |
}
|
421 |
}
|
422 |
-
|
423 |
-
|
424 |
$values = array(
|
425 |
'uid' => $uid,
|
426 |
'user_login' => $user_login,
|
427 |
'user_role' => $user_role,
|
428 |
-
'time' => current_time('mysql'),
|
429 |
'ip' => $_SERVER['REMOTE_ADDR'],
|
430 |
'login_result' => $this->login_success,
|
431 |
'data' => $serialized_data,
|
432 |
);
|
433 |
-
|
434 |
$format = array('%d', '%s', '%s', '%s', '%s', '%s', '%s');
|
435 |
|
436 |
$this->save_data($values, $format);
|
437 |
-
}
|
438 |
|
439 |
|
440 |
function save_data($values, $format)
|
@@ -447,10 +442,10 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
447 |
|
448 |
function make_where_query()
|
449 |
{
|
450 |
-
$where = false;
|
451 |
if( isset($_GET['filter']) && '' != $_GET['filter'] )
|
452 |
{
|
453 |
-
$where['filter'] = "user_login
|
454 |
}
|
455 |
if( isset($_GET['user_role']) && '' != $_GET['user_role'] )
|
456 |
{
|
@@ -475,15 +470,13 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
475 |
{
|
476 |
global $wpdb;
|
477 |
|
478 |
-
$
|
479 |
-
$where = '';
|
480 |
|
481 |
$where = $this->make_where_query();
|
482 |
|
483 |
if( is_array($where) && !empty($where) )
|
484 |
$where = 'WHERE ' . implode(' AND ', $where);
|
485 |
|
486 |
-
$sql = "SELECT * FROM $this->table $where ORDER BY time DESC LIMIT $limit";
|
487 |
$sql = "SELECT * FROM $this->table $where ORDER BY time DESC";
|
488 |
$data = $wpdb->get_results($sql, 'ARRAY_A');
|
489 |
|
@@ -492,28 +485,28 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
492 |
|
493 |
|
494 |
function log_manager()
|
495 |
-
{
|
496 |
-
|
497 |
$log_table = $this->log_table;
|
498 |
-
|
499 |
$log_table->items = $this->log_get_data();
|
500 |
-
$log_table->prepare_items();
|
501 |
|
502 |
echo '<div class="wrap srp">';
|
503 |
echo '<h2>' . __('Login Log', 'sll') . '</h2>';
|
504 |
echo '<div class="tablenav top">';
|
505 |
echo '<div class="alignleft actions">';
|
506 |
echo $this->date_filter();
|
507 |
-
echo '</div>';
|
508 |
|
509 |
$username = ( isset($_GET['filter']) ) ? esc_attr($_GET['filter']) : false;
|
510 |
echo '<form method="get" class="alignright">';
|
511 |
echo '<p class="search-box">';
|
512 |
echo '<input type="hidden" name="page" value="login_log" />';
|
513 |
echo '<label>' . __('Username:', 'sll') . ' </label><input type="text" name="filter" class="filter-username" value="' . $username . '" /> <input class="button" type="submit" value="' . __('Filter User', 'sll') . '" />';
|
514 |
-
echo '<br />';
|
515 |
-
echo '</p>';
|
516 |
-
echo '</form>';
|
517 |
echo '</div>';
|
518 |
echo '<div class="tablenav top">';
|
519 |
|
@@ -527,29 +520,29 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
527 |
echo '<div class="alignright actions">';
|
528 |
$mode = ( isset($_GET['mode']) ) ? esc_attr($_GET['mode']) : false;
|
529 |
$log_table->view_switcher($mode);
|
530 |
-
echo '</div>';
|
531 |
echo '</div>';
|
532 |
-
|
533 |
-
$log_table->display();
|
534 |
-
|
535 |
echo '<form method="get" id="export-login-log">';
|
536 |
echo '<input type="hidden" name="page" value="login_log" />';
|
537 |
echo '<input type="hidden" name="download-login-log" value="true" />';
|
538 |
-
submit_button( __('Export Log to CSV', 'sll'), 'secondary' );
|
539 |
-
echo '</form>';
|
540 |
//if filtered results - add export filtered results button
|
541 |
if( $where = $this->make_where_query() ){
|
542 |
-
|
543 |
echo '<form method="get" id="export-login-log">';
|
544 |
echo '<input type="hidden" name="page" value="login_log" />';
|
545 |
-
echo '<input type="hidden" name="download-login-log" value="true" />';
|
546 |
echo '<input type="hidden" name="where" value="' . esc_attr(serialize($where)) . '" />';
|
547 |
submit_button( __('Export Current Results to CSV', 'sll'), 'secondary' );
|
548 |
-
echo '</form>';
|
549 |
-
|
550 |
}
|
551 |
-
|
552 |
-
echo '</div>';
|
553 |
}
|
554 |
|
555 |
|
@@ -562,11 +555,11 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
562 |
if(!$results)
|
563 |
return;
|
564 |
|
565 |
-
|
566 |
$option = '';
|
567 |
foreach($results as $row)
|
568 |
{
|
569 |
-
//represent month in double digits
|
570 |
$timestamp = mktime(0, 0, 0, $row->month, 1, $row->year);
|
571 |
$month = (strlen($row->month) == 1) ? '0' . $row->month : $row->month;
|
572 |
$datefilter = ( isset($_GET['datefilter']) ) ? $_GET['datefilter'] : false;
|
@@ -585,7 +578,7 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
585 |
function export_to_CSV($where = false){
|
586 |
global $wpdb;
|
587 |
|
588 |
-
//if $where is set, then contemplate WHERE sql query
|
589 |
if( $where ){
|
590 |
$where = unserialize($where);
|
591 |
|
@@ -594,20 +587,20 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
594 |
|
595 |
}
|
596 |
|
597 |
-
$sql = "SELECT * FROM {$this->table}{$where}";
|
598 |
$data = $wpdb->get_results($sql, 'ARRAY_A');
|
599 |
|
600 |
if(!$data)
|
601 |
return;
|
602 |
|
603 |
-
//date string to suffix the file nanme: month - day - year - hour - minute
|
604 |
$suffix = date('n-j-y_H-i');
|
605 |
|
606 |
// send response headers to the browser
|
607 |
header( 'Content-Type: text/csv' );
|
608 |
header( 'Content-Disposition: attachment;filename=login_log_' . $suffix . '.csv');
|
609 |
$fp = fopen('php://output', 'w');
|
610 |
-
|
611 |
$i = 0;
|
612 |
foreach($data as $row){
|
613 |
$tmp = unserialize($row['data']);
|
@@ -621,9 +614,9 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
621 |
fputcsv($fp, $row);
|
622 |
$i++;
|
623 |
}
|
624 |
-
|
625 |
fclose($fp);
|
626 |
-
die();
|
627 |
}
|
628 |
|
629 |
}
|
@@ -632,10 +625,10 @@ if( !class_exists( 'SimpleLoginLog' ) )
|
|
632 |
|
633 |
if( class_exists( 'SimpleLoginLog' ) )
|
634 |
{
|
635 |
-
$sll = new SimpleLoginLog;
|
636 |
//Register for activation
|
637 |
-
register_activation_hook( __FILE__, array(&$sll, 'install') );
|
638 |
-
|
639 |
}
|
640 |
|
641 |
if(!class_exists('WP_List_Table'))
|
@@ -644,11 +637,11 @@ if(!class_exists('WP_List_Table'))
|
|
644 |
}
|
645 |
|
646 |
class SLL_List_Table extends WP_List_Table
|
647 |
-
{
|
648 |
function __construct()
|
649 |
{
|
650 |
global $sll, $_wp_column_headers;
|
651 |
-
|
652 |
//Set parent defaults
|
653 |
parent::__construct( array(
|
654 |
'singular' => 'user', //singular name of the listed records
|
@@ -656,38 +649,38 @@ class SLL_List_Table extends WP_List_Table
|
|
656 |
'ajax' => false //does this table support ajax?
|
657 |
) );
|
658 |
|
659 |
-
$this->data_labels = $sll->data_labels;
|
|
|
|
|
660 |
|
661 |
-
}
|
662 |
-
|
663 |
|
664 |
function column_default($item, $column_name)
|
665 |
{
|
666 |
$item = apply_filters('sll-output-data', $item);
|
667 |
|
668 |
//unset existing filter and pagination
|
669 |
-
$args = wp_parse_args( parse_url($_SERVER["REQUEST_URI"], PHP_URL_QUERY) );
|
670 |
unset($args['filter']);
|
671 |
-
unset($args['paged']);
|
672 |
|
673 |
switch($column_name){
|
674 |
case 'id':
|
675 |
-
case 'uid':
|
676 |
-
case 'time':
|
677 |
case 'ip':
|
678 |
return $item[$column_name];
|
679 |
-
case 'user_login':
|
680 |
-
return "<a href='" . add_query_arg( array('filter' => $item[$column_name]), menu_page_url('login_log', false) ) . "' title='" . __('Filter log by this name', 'sll') . "'>{$item[$column_name]}</a>";
|
681 |
case 'name';
|
682 |
$user_info = get_userdata($item['uid']);
|
683 |
-
return ( is_object($user_info) ) ? $user_info->first_name . " " . $user_info->last_name : false;
|
684 |
case 'login_result':
|
685 |
if ( '' == $item[$column_name]) return '';
|
686 |
return ( '1' == $item[$column_name] ) ? $this->data_labels['Successful'] : '<div class="login-failed">' . $this->data_labels['Failed'] . '</div>';
|
687 |
case 'user_role':
|
688 |
if( !$item['uid'] )
|
689 |
return;
|
690 |
-
|
691 |
$user = new WP_User( $item['uid'] );
|
692 |
if ( !empty( $user->roles ) && is_array( $user->roles ) ) {
|
693 |
foreach($user->roles as $role){
|
@@ -697,7 +690,7 @@ class SLL_List_Table extends WP_List_Table
|
|
697 |
}
|
698 |
break;
|
699 |
case 'data':
|
700 |
-
$data = unserialize($item[$column_name]);
|
701 |
if(is_array($data))
|
702 |
{
|
703 |
$output = '';
|
@@ -709,11 +702,11 @@ class SLL_List_Table extends WP_List_Table
|
|
709 |
$output = ( isset($_GET['mode']) && 'excerpt' == $_GET['mode'] ) ? $output : substr($output, 0, 50) . '...';
|
710 |
|
711 |
if( isset($data[$this->data_labels['Login']]) && $data[$this->data_labels['Login']] == $this->data_labels['Failed'] ){
|
712 |
-
return '<div class="login-failed">' . $output . '</div>';
|
713 |
}
|
714 |
return $output;
|
715 |
-
}
|
716 |
-
break;
|
717 |
default:
|
718 |
return $item[$column_name];
|
719 |
}
|
@@ -721,19 +714,19 @@ class SLL_List_Table extends WP_List_Table
|
|
721 |
|
722 |
|
723 |
function get_columns()
|
724 |
-
{
|
725 |
global $status;
|
726 |
$columns = array(
|
727 |
-
'id' =>
|
728 |
-
'uid' =>
|
729 |
-
'user_login' =>
|
730 |
-
'user_role' =>
|
731 |
-
'name' =>
|
732 |
-
'time' =>
|
733 |
-
'ip' =>
|
734 |
-
'login_result' =>
|
735 |
-
'data' =>
|
736 |
-
);
|
737 |
return $columns;
|
738 |
}
|
739 |
|
@@ -755,14 +748,14 @@ class SLL_List_Table extends WP_List_Table
|
|
755 |
{
|
756 |
//creating class="current" variables
|
757 |
if( !isset($_GET['result']) ){
|
758 |
-
$all = 'class="current"';
|
759 |
-
$success = '';
|
760 |
$failed = '';
|
761 |
}else{
|
762 |
$all = '';
|
763 |
$success = ( '1' == $_GET['result'] ) ? 'class="current"' : '';
|
764 |
-
$failed = ( '0' == $_GET['result'] ) ? 'class="current"' : '';
|
765 |
-
}
|
766 |
|
767 |
//get number of successful and failed logins so we can display them in parentheces for each view
|
768 |
global $wpdb, $sll;
|
@@ -775,14 +768,14 @@ class SLL_List_Table extends WP_List_Table
|
|
775 |
}else{
|
776 |
$where = false;
|
777 |
}
|
778 |
-
|
779 |
$where3 = $where2 = $where1 = $where;
|
780 |
$where2['login_result'] = "login_result = '1'";
|
781 |
$where3['login_result'] = "login_result = '0'";
|
782 |
-
|
783 |
if(is_array($where1) && !empty($where1)){
|
784 |
-
$where1 = 'WHERE ' . implode(' AND ', $where1);
|
785 |
-
}
|
786 |
$where2 = 'WHERE ' . implode(' AND ', $where2);
|
787 |
$where3 = 'WHERE ' . implode(' AND ', $where3);
|
788 |
|
@@ -798,9 +791,9 @@ class SLL_List_Table extends WP_List_Table
|
|
798 |
if( isset($_GET['datefilter']) && !empty($_GET['datefilter']) ){
|
799 |
$year = substr($_GET['datefilter'], 0, 4);
|
800 |
$month = substr($_GET['datefilter'], -2);
|
801 |
-
$timestamp = mktime(0, 0, 0, $month, 1, $year);
|
802 |
$date_label = date('F', $timestamp) . ' ' . $year . ' ';
|
803 |
-
}
|
804 |
|
805 |
//get args from the URL
|
806 |
$args = wp_parse_args( parse_url($_SERVER["REQUEST_URI"], PHP_URL_QUERY) );
|
@@ -825,7 +818,7 @@ class SLL_List_Table extends WP_List_Table
|
|
825 |
|
826 |
return $views;
|
827 |
}
|
828 |
-
|
829 |
|
830 |
function prepare_items()
|
831 |
{
|
@@ -833,11 +826,12 @@ class SLL_List_Table extends WP_List_Table
|
|
833 |
|
834 |
/**
|
835 |
* First, lets decide how many records per page to show
|
836 |
-
*/
|
837 |
-
$per_page_option = $screen->id . '_per_page';
|
838 |
$per_page = get_option($per_page_option, 20);
|
839 |
-
|
840 |
-
|
|
|
841 |
/**
|
842 |
* REQUIRED. Now we need to define our column headers. This includes a complete
|
843 |
* array of columns to be displayed (slugs & titles), a list of columns
|
@@ -848,43 +842,43 @@ class SLL_List_Table extends WP_List_Table
|
|
848 |
$columns = $this->get_columns();
|
849 |
$hidden_cols = get_user_option( 'manage' . $screen->id . 'columnshidden' );
|
850 |
$hidden = ( $hidden_cols ) ? $hidden_cols : array();
|
851 |
-
$sortable = $this->get_sortable_columns();
|
852 |
-
|
853 |
-
|
854 |
/**
|
855 |
-
* REQUIRED. Finally, we build an array to be used by the class for column
|
856 |
* headers. The $this->_column_headers property takes an array which contains
|
857 |
* 3 other arrays. One for all columns, one for hidden columns, and one
|
858 |
* for sortable columns.
|
859 |
*/
|
860 |
-
$this->_column_headers = array($columns, $hidden, $sortable);
|
861 |
$columns = get_column_headers( $screen );
|
862 |
-
|
863 |
|
864 |
/**
|
865 |
* Optional. You can handle your bulk actions however you see fit. In this
|
866 |
* case, we'll handle them within our package just to keep things clean.
|
867 |
*/
|
868 |
//$this->process_bulk_action();
|
869 |
-
|
870 |
-
|
871 |
/**
|
872 |
* Instead of querying a database, we're going to fetch the example data
|
873 |
-
* property we created for use in this plugin. This makes this example
|
874 |
-
* package slightly different than one you might build on your own. In
|
875 |
-
* this example, we'll be using array manipulation to sort and paginate
|
876 |
-
* our data. In a real-world implementation, you will probably want to
|
877 |
* use sort and pagination data to build a custom query instead, as you'll
|
878 |
* be able to use your precisely-queried data immediately.
|
879 |
*/
|
880 |
$data = $this->items;
|
881 |
-
|
882 |
-
|
883 |
/**
|
884 |
* This checks for sorting input and sorts the data in our array accordingly.
|
885 |
-
*
|
886 |
-
* In a real-world situation involving a database, you would probably want
|
887 |
-
* to handle sorting by passing the 'orderby' and 'order' values directly
|
888 |
* to a custom query. The returned data will be pre-sorted, and this array
|
889 |
* sorting technique would be unnecessary.
|
890 |
*/
|
@@ -895,51 +889,51 @@ class SLL_List_Table extends WP_List_Table
|
|
895 |
return ($order==='asc') ? $result : -$result; //Send final sort direction to usort
|
896 |
}
|
897 |
usort($data, 'usort_reorder');
|
898 |
-
|
899 |
-
|
900 |
/***********************************************************************
|
901 |
* ---------------------------------------------------------------------
|
902 |
* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
903 |
-
*
|
904 |
* In a real-world situation, this is where you would place your query.
|
905 |
-
*
|
906 |
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
907 |
* ---------------------------------------------------------------------
|
908 |
**********************************************************************/
|
909 |
-
|
910 |
-
|
911 |
/**
|
912 |
-
* REQUIRED for pagination. Let's figure out what page the user is currently
|
913 |
-
* looking at. We'll need this later, so you should always include it in
|
914 |
* your own package classes.
|
915 |
*/
|
916 |
$current_page = $this->get_pagenum();
|
917 |
-
|
918 |
/**
|
919 |
-
* REQUIRED for pagination. Let's check how many items are in our data array.
|
920 |
-
* In real-world use, this would be the total number of items in your database,
|
921 |
-
* without filtering. We'll need this later, so you should always include it
|
922 |
* in your own package classes.
|
923 |
*/
|
924 |
$total_items = count($data);
|
925 |
-
|
926 |
-
|
927 |
/**
|
928 |
* The WP_List_Table class does not handle pagination for us, so we need
|
929 |
* to ensure that the data is trimmed to only the current page. We can use
|
930 |
-
* array_slice() to
|
931 |
*/
|
932 |
$data = array_slice($data,(($current_page-1)*$per_page),$per_page);
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
/**
|
937 |
-
* REQUIRED. Now we can add our *sorted* data to the items property, where
|
938 |
* it can be used by the rest of the class.
|
939 |
*/
|
940 |
$this->items = $data;
|
941 |
-
|
942 |
-
|
943 |
/**
|
944 |
* REQUIRED. We also have to register our pagination options & calculations.
|
945 |
*/
|
@@ -950,5 +944,5 @@ class SLL_List_Table extends WP_List_Table
|
|
950 |
) );
|
951 |
|
952 |
}
|
953 |
-
|
954 |
}
|
4 |
Plugin URI: http://simplerealtytheme.com
|
5 |
Description: This plugin keeps a log of WordPress user logins. Offers user filtering and export features.
|
6 |
Author: Max Chirkov
|
7 |
+
Version: 0.9.3
|
8 |
Author URI: http://SimpleRealtyTheme.com
|
9 |
*/
|
10 |
|
11 |
//TODO: add cleanup method on uninstall
|
12 |
|
13 |
if( !class_exists( 'SimpleLoginLog' ) )
|
14 |
+
{
|
15 |
class SimpleLoginLog {
|
16 |
private $db_ver = "1.2";
|
17 |
public $table = 'simple_login_log';
|
18 |
private $log_duration = null; //days
|
19 |
private $opt_name = 'simple_login_log';
|
20 |
private $opt = false;
|
21 |
+
private $login_success = 1;
|
22 |
public $data_labels = array();
|
23 |
|
24 |
+
|
25 |
function __construct()
|
26 |
{
|
27 |
global $wpdb;
|
31 |
//Get plugin's DB version
|
32 |
$this->installed_ver = get_option( "sll_db_ver" );
|
33 |
|
34 |
+
//Check if download was initiated
|
35 |
$download = @esc_attr( $_GET['download-login-log'] );
|
36 |
if($download)
|
37 |
{
|
38 |
$where = ( isset($_GET['where']) ) ? $_GET['where'] : false;
|
39 |
$this->export_to_CSV($where);
|
40 |
+
}
|
41 |
|
42 |
|
43 |
add_action( 'admin_menu', array(&$this, 'sll_admin_menu') );
|
46 |
|
47 |
//check if db needs to be upgraded after plugin update was completed
|
48 |
add_action('plugins_loaded', array(&$this, 'update_db_check') );
|
49 |
+
|
50 |
//Init login actions
|
51 |
+
add_action( 'init', array(&$this, 'init_login_actions') );
|
52 |
+
|
53 |
//Style the log table
|
54 |
add_action( 'admin_head', array(&$this, 'admin_header') );
|
55 |
|
58 |
add_action('truncate_sll', array(&$this, 'cron') );
|
59 |
|
60 |
//Load Locale
|
61 |
+
add_action('plugins_loaded', array(&$this, 'load_locale'), 10 );
|
62 |
|
63 |
//For translation purposes
|
64 |
$this->data_labels = array(
|
85 |
|
86 |
|
87 |
function load_locale()
|
88 |
+
{
|
89 |
+
load_plugin_textdomain( 'sll', false, basename(dirname(__FILE__)) . '/languages/' );
|
|
|
|
|
|
|
|
|
|
|
90 |
}
|
91 |
|
92 |
|
93 |
function cron()
|
94 |
+
{
|
95 |
SimpleLoginLog::truncate_log();
|
96 |
}
|
97 |
|
102 |
//execute only on login_log page, othewise return null
|
103 |
$page = ( isset($_GET['page']) ) ? esc_attr($_GET['page']) : false;
|
104 |
if( 'login_log' != $page )
|
105 |
+
return;
|
106 |
|
107 |
$current_screen = get_current_screen();
|
108 |
|
114 |
if( isset($_REQUEST['wp_screen_options']) && isset($_REQUEST['wp_screen_options']['value']) )
|
115 |
{
|
116 |
update_option( $per_page_option, esc_html($_REQUEST['wp_screen_options']['value']) );
|
117 |
+
}
|
118 |
|
119 |
//prepare options for display
|
120 |
|
121 |
//if per page option is not set, use default
|
122 |
+
$per_page_val = get_option($per_page_option, 20);
|
123 |
$args = array('label' => __('Records', 'sll'), 'default' => $per_page_val );
|
124 |
|
125 |
//display options
|
126 |
+
add_screen_option($per_page_field, $args);
|
127 |
+
$_per_page = get_option('users_page_login_log_per_page');
|
128 |
|
129 |
//needs to be initialized early enough to pre-fill screen options section in the upper (hidden) area.
|
130 |
$this->log_table = new SLL_List_Table;
|
136 |
//condition to check if "log failed attemts" option is selected
|
137 |
|
138 |
//Action on successfull login
|
139 |
+
add_action( 'wp_login', array(&$this, 'login_success') );
|
140 |
|
141 |
+
//Action on failed login
|
142 |
+
if( isset($this->opt['failed_attempts']) ){
|
143 |
add_action( 'wp_login_failed', array(&$this, 'login_failed') );
|
144 |
}
|
145 |
|
161 |
|
162 |
|
163 |
function init_scheduled_events()
|
164 |
+
{
|
165 |
|
166 |
$log_duration = get_option('simple_login_log');
|
167 |
|
168 |
+
if ( $log_duration && !wp_next_scheduled( 'truncate_sll' ) )
|
169 |
+
{
|
170 |
$start = time();
|
171 |
wp_schedule_event($start, 'daily', 'truncate_sll');
|
172 |
}elseif( !$log_duration || 0 == $log_duration)
|
173 |
{
|
174 |
$timestamp = wp_next_scheduled( 'truncate_sll' );
|
175 |
(!$timestamp) ? false : wp_unschedule_event($timestamp, 'truncate_sll');
|
176 |
+
|
177 |
}
|
178 |
}
|
179 |
|
183 |
|
184 |
//clean up old cron jobs that no longer exist
|
185 |
wp_clear_scheduled_hook('truncate_log');
|
186 |
+
wp_clear_scheduled_hook('SimpleLoginLog::truncate_log');
|
187 |
}
|
188 |
|
189 |
|
193 |
|
194 |
$opt = get_option('simple_login_log');
|
195 |
$log_duration = (int)$opt['log_duration'];
|
196 |
+
|
197 |
$table = $wpdb->prefix . 'simple_login_log';
|
198 |
|
199 |
+
if( 0 < $log_duration ){
|
200 |
$sql = $wpdb->prepare( "DELETE FROM {$table} WHERE time < DATE_SUB(CURDATE(),INTERVAL %d DAY)", $log_duration);
|
201 |
+
$wpdb->query($sql);
|
202 |
}
|
203 |
+
|
204 |
}
|
205 |
|
206 |
|
208 |
* Runs via plugin activation hook & creates a database
|
209 |
*/
|
210 |
function install()
|
211 |
+
{
|
212 |
global $wpdb;
|
213 |
|
214 |
if( $this->installed_ver != $this->db_ver )
|
215 |
{
|
216 |
//if table does't exist, create a new one
|
217 |
if( !$wpdb->get_row("SHOW TABLES LIKE '{$this->table}'") ){
|
218 |
+
$sql = "CREATE TABLE " . $this->table . "
|
219 |
(
|
220 |
id INT( 11 ) NOT NULL AUTO_INCREMENT ,
|
221 |
uid INT( 11 ) NOT NULL ,
|
222 |
user_login VARCHAR( 60 ) NOT NULL ,
|
223 |
user_role VARCHAR( 30 ) NOT NULL ,
|
224 |
+
time DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL ,
|
225 |
ip VARCHAR( 100 ) NOT NULL ,
|
226 |
login_result VARCHAR (1) ,
|
227 |
data LONGTEXT NOT NULL ,
|
235 |
update_option( "sll_db_ver", $this->db_ver );
|
236 |
}
|
237 |
}
|
238 |
+
|
239 |
+
|
240 |
}
|
241 |
|
242 |
+
|
243 |
/**
|
244 |
* Checks if the installed database version is the same as the db version of the current plugin
|
245 |
* calles the version specific function if upgrade is required
|
266 |
*/
|
267 |
function db_update_1_1()
|
268 |
{
|
269 |
+
|
270 |
/* this version adds a new field "login_result"
|
271 |
* check if this field exists
|
272 |
*/
|
279 |
$this->install();
|
280 |
return;
|
281 |
}
|
282 |
+
|
283 |
$field_names = array_keys( $fields );
|
284 |
+
|
285 |
if( !array_search('login_result', $field_names) )
|
286 |
+
{
|
287 |
//add the new field since it doesn't exist
|
288 |
$sql = "ALTER TABLE {$this->table} ADD COLUMN login_result varchar(1) NOT NULL AFTER ip, ADD INDEX (login_result);";
|
289 |
$insert = $wpdb->query( $sql );
|
290 |
+
|
291 |
//update version record if it has been updated
|
292 |
if( false !== $insert )
|
293 |
update_option( "sll_db_ver", $this->db_ver );
|
294 |
|
295 |
}
|
296 |
+
|
297 |
}
|
298 |
|
299 |
|
311 |
$this->install();
|
312 |
return;
|
313 |
}
|
314 |
+
|
315 |
$field_names = array_keys( $fields );
|
316 |
+
|
317 |
if( !array_search('user_role', $field_names) )
|
318 |
+
{
|
319 |
//add the new field since it doesn't exist
|
320 |
$sql = "ALTER TABLE {$this->table} ADD COLUMN user_role varchar(30) NOT NULL AFTER user_login;";
|
321 |
$insert = $wpdb->query( $sql );
|
322 |
+
|
323 |
//update version record if it has been updated
|
324 |
if( false !== $insert )
|
325 |
update_option( "sll_db_ver", $this->db_ver );
|
326 |
+
|
327 |
}
|
328 |
}
|
329 |
+
|
330 |
|
331 |
//Initializing Settings
|
332 |
function settings_api_init()
|
333 |
{
|
334 |
+
add_settings_section('simple_login_log', __('Simple Login Log', 'sll'), array(&$this, 'sll_settings'), 'general');
|
335 |
add_settings_field('field_log_duration', __('Truncate Log Entries', 'sll'), array(&$this, 'field_log_duration'), 'general', 'simple_login_log');
|
336 |
add_settings_field('field_log_failed_attempts', __('Log Failed Attempts', 'sll'), array(&$this, 'field_log_failed_attempts'), 'general', 'simple_login_log');
|
337 |
+
register_setting( 'general', 'simple_login_log' );
|
338 |
|
339 |
}
|
340 |
|
346 |
|
347 |
|
348 |
function sll_settings()
|
349 |
+
{
|
350 |
//content that goes before the fields output
|
351 |
}
|
352 |
|
353 |
|
354 |
function field_log_duration()
|
355 |
{
|
356 |
+
$duration = (null !== $this->opt['log_duration']) ? $this->opt['log_duration'] : $this->log_duration;
|
357 |
+
$output = '<input type="text" value="' . $duration . '" name="simple_login_log[log_duration]" size="10" class="code" /> ' . __('days and older.', 'sll');
|
358 |
echo $output;
|
359 |
echo "<p>" . __("Leave empty or enter 0 if you don't want the log to be truncated.", 'sll') . "</p>";
|
360 |
|
361 |
//since we're on the General Settings page - update cron schedule if settings has been updated
|
362 |
+
if( isset($_REQUEST['settings-updated']) ){
|
363 |
+
wp_clear_scheduled_hook('truncate_sll');
|
364 |
//$this->init_scheduled_events();
|
365 |
}
|
366 |
}
|
377 |
{
|
378 |
$page = ( isset($_GET['page']) ) ? esc_attr($_GET['page']) : false;
|
379 |
if( 'login_log' != $page )
|
380 |
+
return;
|
381 |
|
382 |
echo '<style type="text/css">';
|
383 |
echo '.wp-list-table .column-id { width: 5%; }';
|
395 |
//Catch messages on successful login
|
396 |
function login_action($user_login)
|
397 |
{
|
398 |
+
|
399 |
$userdata = get_user_by('login', $user_login);
|
400 |
|
401 |
$uid = ($userdata && $userdata->ID) ? $userdata->ID : 0;
|
402 |
+
|
403 |
$data[$this->data_labels['Login']] = ( 1 == $this->login_success ) ? $this->data_labels['Successful'] : $this->data_labels['Failed'];
|
404 |
+
if ( isset( $_REQUEST['redirect_to'] ) ) { $data[$this->data_labels['Login Redirect']] = $_REQUEST['redirect_to']; }
|
405 |
$data[$this->data_labels['User Agent']] = $_SERVER['HTTP_USER_AGENT'];
|
406 |
+
|
407 |
$serialized_data = serialize($data);
|
408 |
|
409 |
//get user role
|
414 |
$user_role = implode(', ', $user->roles);
|
415 |
}
|
416 |
}
|
417 |
+
|
418 |
+
|
419 |
$values = array(
|
420 |
'uid' => $uid,
|
421 |
'user_login' => $user_login,
|
422 |
'user_role' => $user_role,
|
423 |
+
'time' => current_time('mysql'),
|
424 |
'ip' => $_SERVER['REMOTE_ADDR'],
|
425 |
'login_result' => $this->login_success,
|
426 |
'data' => $serialized_data,
|
427 |
);
|
428 |
+
|
429 |
$format = array('%d', '%s', '%s', '%s', '%s', '%s', '%s');
|
430 |
|
431 |
$this->save_data($values, $format);
|
432 |
+
}
|
433 |
|
434 |
|
435 |
function save_data($values, $format)
|
442 |
|
443 |
function make_where_query()
|
444 |
{
|
445 |
+
$where = false;
|
446 |
if( isset($_GET['filter']) && '' != $_GET['filter'] )
|
447 |
{
|
448 |
+
$where['filter'] = "(user_login LIKE '%{$_GET['filter']}%' OR ip LIKE '%{$_GET['filter']}%')";
|
449 |
}
|
450 |
if( isset($_GET['user_role']) && '' != $_GET['user_role'] )
|
451 |
{
|
470 |
{
|
471 |
global $wpdb;
|
472 |
|
473 |
+
$where = '';
|
|
|
474 |
|
475 |
$where = $this->make_where_query();
|
476 |
|
477 |
if( is_array($where) && !empty($where) )
|
478 |
$where = 'WHERE ' . implode(' AND ', $where);
|
479 |
|
|
|
480 |
$sql = "SELECT * FROM $this->table $where ORDER BY time DESC";
|
481 |
$data = $wpdb->get_results($sql, 'ARRAY_A');
|
482 |
|
485 |
|
486 |
|
487 |
function log_manager()
|
488 |
+
{
|
489 |
+
|
490 |
$log_table = $this->log_table;
|
491 |
+
|
492 |
$log_table->items = $this->log_get_data();
|
493 |
+
$log_table->prepare_items();
|
494 |
|
495 |
echo '<div class="wrap srp">';
|
496 |
echo '<h2>' . __('Login Log', 'sll') . '</h2>';
|
497 |
echo '<div class="tablenav top">';
|
498 |
echo '<div class="alignleft actions">';
|
499 |
echo $this->date_filter();
|
500 |
+
echo '</div>';
|
501 |
|
502 |
$username = ( isset($_GET['filter']) ) ? esc_attr($_GET['filter']) : false;
|
503 |
echo '<form method="get" class="alignright">';
|
504 |
echo '<p class="search-box">';
|
505 |
echo '<input type="hidden" name="page" value="login_log" />';
|
506 |
echo '<label>' . __('Username:', 'sll') . ' </label><input type="text" name="filter" class="filter-username" value="' . $username . '" /> <input class="button" type="submit" value="' . __('Filter User', 'sll') . '" />';
|
507 |
+
echo '<br />';
|
508 |
+
echo '</p>';
|
509 |
+
echo '</form>';
|
510 |
echo '</div>';
|
511 |
echo '<div class="tablenav top">';
|
512 |
|
520 |
echo '<div class="alignright actions">';
|
521 |
$mode = ( isset($_GET['mode']) ) ? esc_attr($_GET['mode']) : false;
|
522 |
$log_table->view_switcher($mode);
|
523 |
+
echo '</div>';
|
524 |
echo '</div>';
|
525 |
+
|
526 |
+
$log_table->display();
|
527 |
+
|
528 |
echo '<form method="get" id="export-login-log">';
|
529 |
echo '<input type="hidden" name="page" value="login_log" />';
|
530 |
echo '<input type="hidden" name="download-login-log" value="true" />';
|
531 |
+
submit_button( __('Export Log to CSV', 'sll'), 'secondary' );
|
532 |
+
echo '</form>';
|
533 |
//if filtered results - add export filtered results button
|
534 |
if( $where = $this->make_where_query() ){
|
535 |
+
|
536 |
echo '<form method="get" id="export-login-log">';
|
537 |
echo '<input type="hidden" name="page" value="login_log" />';
|
538 |
+
echo '<input type="hidden" name="download-login-log" value="true" />';
|
539 |
echo '<input type="hidden" name="where" value="' . esc_attr(serialize($where)) . '" />';
|
540 |
submit_button( __('Export Current Results to CSV', 'sll'), 'secondary' );
|
541 |
+
echo '</form>';
|
542 |
+
|
543 |
}
|
544 |
+
|
545 |
+
echo '</div>';
|
546 |
}
|
547 |
|
548 |
|
555 |
if(!$results)
|
556 |
return;
|
557 |
|
558 |
+
|
559 |
$option = '';
|
560 |
foreach($results as $row)
|
561 |
{
|
562 |
+
//represent month in double digits
|
563 |
$timestamp = mktime(0, 0, 0, $row->month, 1, $row->year);
|
564 |
$month = (strlen($row->month) == 1) ? '0' . $row->month : $row->month;
|
565 |
$datefilter = ( isset($_GET['datefilter']) ) ? $_GET['datefilter'] : false;
|
578 |
function export_to_CSV($where = false){
|
579 |
global $wpdb;
|
580 |
|
581 |
+
//if $where is set, then contemplate WHERE sql query
|
582 |
if( $where ){
|
583 |
$where = unserialize($where);
|
584 |
|
587 |
|
588 |
}
|
589 |
|
590 |
+
$sql = "SELECT * FROM {$this->table}{$where}";
|
591 |
$data = $wpdb->get_results($sql, 'ARRAY_A');
|
592 |
|
593 |
if(!$data)
|
594 |
return;
|
595 |
|
596 |
+
//date string to suffix the file nanme: month - day - year - hour - minute
|
597 |
$suffix = date('n-j-y_H-i');
|
598 |
|
599 |
// send response headers to the browser
|
600 |
header( 'Content-Type: text/csv' );
|
601 |
header( 'Content-Disposition: attachment;filename=login_log_' . $suffix . '.csv');
|
602 |
$fp = fopen('php://output', 'w');
|
603 |
+
|
604 |
$i = 0;
|
605 |
foreach($data as $row){
|
606 |
$tmp = unserialize($row['data']);
|
614 |
fputcsv($fp, $row);
|
615 |
$i++;
|
616 |
}
|
617 |
+
|
618 |
fclose($fp);
|
619 |
+
die();
|
620 |
}
|
621 |
|
622 |
}
|
625 |
|
626 |
if( class_exists( 'SimpleLoginLog' ) )
|
627 |
{
|
628 |
+
$sll = new SimpleLoginLog;
|
629 |
//Register for activation
|
630 |
+
register_activation_hook( __FILE__, array(&$sll, 'install') );
|
631 |
+
|
632 |
}
|
633 |
|
634 |
if(!class_exists('WP_List_Table'))
|
637 |
}
|
638 |
|
639 |
class SLL_List_Table extends WP_List_Table
|
640 |
+
{
|
641 |
function __construct()
|
642 |
{
|
643 |
global $sll, $_wp_column_headers;
|
644 |
+
|
645 |
//Set parent defaults
|
646 |
parent::__construct( array(
|
647 |
'singular' => 'user', //singular name of the listed records
|
649 |
'ajax' => false //does this table support ajax?
|
650 |
) );
|
651 |
|
652 |
+
$this->data_labels = $sll->data_labels;
|
653 |
+
|
654 |
+
}
|
655 |
|
|
|
|
|
656 |
|
657 |
function column_default($item, $column_name)
|
658 |
{
|
659 |
$item = apply_filters('sll-output-data', $item);
|
660 |
|
661 |
//unset existing filter and pagination
|
662 |
+
$args = wp_parse_args( parse_url($_SERVER["REQUEST_URI"], PHP_URL_QUERY) );
|
663 |
unset($args['filter']);
|
664 |
+
unset($args['paged']);
|
665 |
|
666 |
switch($column_name){
|
667 |
case 'id':
|
668 |
+
case 'uid':
|
669 |
+
case 'time':
|
670 |
case 'ip':
|
671 |
return $item[$column_name];
|
672 |
+
case 'user_login':
|
673 |
+
return "<a href='" . add_query_arg( array('filter' => $item[$column_name]), menu_page_url('login_log', false) ) . "' title='" . __('Filter log by this name', 'sll') . "'>{$item[$column_name]}</a>";
|
674 |
case 'name';
|
675 |
$user_info = get_userdata($item['uid']);
|
676 |
+
return ( is_object($user_info) ) ? $user_info->first_name . " " . $user_info->last_name : false;
|
677 |
case 'login_result':
|
678 |
if ( '' == $item[$column_name]) return '';
|
679 |
return ( '1' == $item[$column_name] ) ? $this->data_labels['Successful'] : '<div class="login-failed">' . $this->data_labels['Failed'] . '</div>';
|
680 |
case 'user_role':
|
681 |
if( !$item['uid'] )
|
682 |
return;
|
683 |
+
|
684 |
$user = new WP_User( $item['uid'] );
|
685 |
if ( !empty( $user->roles ) && is_array( $user->roles ) ) {
|
686 |
foreach($user->roles as $role){
|
690 |
}
|
691 |
break;
|
692 |
case 'data':
|
693 |
+
$data = unserialize($item[$column_name]);
|
694 |
if(is_array($data))
|
695 |
{
|
696 |
$output = '';
|
702 |
$output = ( isset($_GET['mode']) && 'excerpt' == $_GET['mode'] ) ? $output : substr($output, 0, 50) . '...';
|
703 |
|
704 |
if( isset($data[$this->data_labels['Login']]) && $data[$this->data_labels['Login']] == $this->data_labels['Failed'] ){
|
705 |
+
return '<div class="login-failed">' . $output . '</div>';
|
706 |
}
|
707 |
return $output;
|
708 |
+
}
|
709 |
+
break;
|
710 |
default:
|
711 |
return $item[$column_name];
|
712 |
}
|
714 |
|
715 |
|
716 |
function get_columns()
|
717 |
+
{
|
718 |
global $status;
|
719 |
$columns = array(
|
720 |
+
'id' => __('#', 'sll'),
|
721 |
+
'uid' => __('User ID', 'sll'),
|
722 |
+
'user_login' => __('Username', 'sll'),
|
723 |
+
'user_role' => __('User Role', 'sll'),
|
724 |
+
'name' => __('Name', 'sll'),
|
725 |
+
'time' => __('Time', 'sll'),
|
726 |
+
'ip' => __('IP Address', 'sll'),
|
727 |
+
'login_result' => __('Login Result', 'sll'),
|
728 |
+
'data' => __('Data', 'sll'),
|
729 |
+
);
|
730 |
return $columns;
|
731 |
}
|
732 |
|
748 |
{
|
749 |
//creating class="current" variables
|
750 |
if( !isset($_GET['result']) ){
|
751 |
+
$all = 'class="current"';
|
752 |
+
$success = '';
|
753 |
$failed = '';
|
754 |
}else{
|
755 |
$all = '';
|
756 |
$success = ( '1' == $_GET['result'] ) ? 'class="current"' : '';
|
757 |
+
$failed = ( '0' == $_GET['result'] ) ? 'class="current"' : '';
|
758 |
+
}
|
759 |
|
760 |
//get number of successful and failed logins so we can display them in parentheces for each view
|
761 |
global $wpdb, $sll;
|
768 |
}else{
|
769 |
$where = false;
|
770 |
}
|
771 |
+
|
772 |
$where3 = $where2 = $where1 = $where;
|
773 |
$where2['login_result'] = "login_result = '1'";
|
774 |
$where3['login_result'] = "login_result = '0'";
|
775 |
+
|
776 |
if(is_array($where1) && !empty($where1)){
|
777 |
+
$where1 = 'WHERE ' . implode(' AND ', $where1);
|
778 |
+
}
|
779 |
$where2 = 'WHERE ' . implode(' AND ', $where2);
|
780 |
$where3 = 'WHERE ' . implode(' AND ', $where3);
|
781 |
|
791 |
if( isset($_GET['datefilter']) && !empty($_GET['datefilter']) ){
|
792 |
$year = substr($_GET['datefilter'], 0, 4);
|
793 |
$month = substr($_GET['datefilter'], -2);
|
794 |
+
$timestamp = mktime(0, 0, 0, $month, 1, $year);
|
795 |
$date_label = date('F', $timestamp) . ' ' . $year . ' ';
|
796 |
+
}
|
797 |
|
798 |
//get args from the URL
|
799 |
$args = wp_parse_args( parse_url($_SERVER["REQUEST_URI"], PHP_URL_QUERY) );
|
818 |
|
819 |
return $views;
|
820 |
}
|
821 |
+
|
822 |
|
823 |
function prepare_items()
|
824 |
{
|
826 |
|
827 |
/**
|
828 |
* First, lets decide how many records per page to show
|
829 |
+
*/
|
830 |
+
$per_page_option = $screen->id . '_per_page';
|
831 |
$per_page = get_option($per_page_option, 20);
|
832 |
+
$per_page = ($per_page != false) ? $per_page : 20;
|
833 |
+
|
834 |
+
|
835 |
/**
|
836 |
* REQUIRED. Now we need to define our column headers. This includes a complete
|
837 |
* array of columns to be displayed (slugs & titles), a list of columns
|
842 |
$columns = $this->get_columns();
|
843 |
$hidden_cols = get_user_option( 'manage' . $screen->id . 'columnshidden' );
|
844 |
$hidden = ( $hidden_cols ) ? $hidden_cols : array();
|
845 |
+
$sortable = $this->get_sortable_columns();
|
846 |
+
|
847 |
+
|
848 |
/**
|
849 |
+
* REQUIRED. Finally, we build an array to be used by the class for column
|
850 |
* headers. The $this->_column_headers property takes an array which contains
|
851 |
* 3 other arrays. One for all columns, one for hidden columns, and one
|
852 |
* for sortable columns.
|
853 |
*/
|
854 |
+
$this->_column_headers = array($columns, $hidden, $sortable);
|
855 |
$columns = get_column_headers( $screen );
|
856 |
+
|
857 |
|
858 |
/**
|
859 |
* Optional. You can handle your bulk actions however you see fit. In this
|
860 |
* case, we'll handle them within our package just to keep things clean.
|
861 |
*/
|
862 |
//$this->process_bulk_action();
|
863 |
+
|
864 |
+
|
865 |
/**
|
866 |
* Instead of querying a database, we're going to fetch the example data
|
867 |
+
* property we created for use in this plugin. This makes this example
|
868 |
+
* package slightly different than one you might build on your own. In
|
869 |
+
* this example, we'll be using array manipulation to sort and paginate
|
870 |
+
* our data. In a real-world implementation, you will probably want to
|
871 |
* use sort and pagination data to build a custom query instead, as you'll
|
872 |
* be able to use your precisely-queried data immediately.
|
873 |
*/
|
874 |
$data = $this->items;
|
875 |
+
|
876 |
+
|
877 |
/**
|
878 |
* This checks for sorting input and sorts the data in our array accordingly.
|
879 |
+
*
|
880 |
+
* In a real-world situation involving a database, you would probably want
|
881 |
+
* to handle sorting by passing the 'orderby' and 'order' values directly
|
882 |
* to a custom query. The returned data will be pre-sorted, and this array
|
883 |
* sorting technique would be unnecessary.
|
884 |
*/
|
889 |
return ($order==='asc') ? $result : -$result; //Send final sort direction to usort
|
890 |
}
|
891 |
usort($data, 'usort_reorder');
|
892 |
+
|
893 |
+
|
894 |
/***********************************************************************
|
895 |
* ---------------------------------------------------------------------
|
896 |
* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
897 |
+
*
|
898 |
* In a real-world situation, this is where you would place your query.
|
899 |
+
*
|
900 |
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
901 |
* ---------------------------------------------------------------------
|
902 |
**********************************************************************/
|
903 |
+
|
904 |
+
|
905 |
/**
|
906 |
+
* REQUIRED for pagination. Let's figure out what page the user is currently
|
907 |
+
* looking at. We'll need this later, so you should always include it in
|
908 |
* your own package classes.
|
909 |
*/
|
910 |
$current_page = $this->get_pagenum();
|
911 |
+
|
912 |
/**
|
913 |
+
* REQUIRED for pagination. Let's check how many items are in our data array.
|
914 |
+
* In real-world use, this would be the total number of items in your database,
|
915 |
+
* without filtering. We'll need this later, so you should always include it
|
916 |
* in your own package classes.
|
917 |
*/
|
918 |
$total_items = count($data);
|
919 |
+
|
920 |
+
|
921 |
/**
|
922 |
* The WP_List_Table class does not handle pagination for us, so we need
|
923 |
* to ensure that the data is trimmed to only the current page. We can use
|
924 |
+
* array_slice() to
|
925 |
*/
|
926 |
$data = array_slice($data,(($current_page-1)*$per_page),$per_page);
|
927 |
+
|
928 |
+
|
929 |
+
|
930 |
/**
|
931 |
+
* REQUIRED. Now we can add our *sorted* data to the items property, where
|
932 |
* it can be used by the rest of the class.
|
933 |
*/
|
934 |
$this->items = $data;
|
935 |
+
|
936 |
+
|
937 |
/**
|
938 |
* REQUIRED. We also have to register our pagination options & calculations.
|
939 |
*/
|
944 |
) );
|
945 |
|
946 |
}
|
947 |
+
|
948 |
}
|
uninstall.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( !defined( 'WP_UNINSTALL_PLUGIN' ) )
|
4 |
+
exit ();
|
5 |
+
|
6 |
+
global $wpdb;
|
7 |
+
//Delete table
|
8 |
+
$sql = "DROP TABLE {$wpdb->prefix}simple_login_log";
|
9 |
+
$wpdb->query($sql);
|
10 |
+
|
11 |
+
//Delete options
|
12 |
+
delete_option('sll_db_ver');
|
13 |
+
delete_option('simple_login_log');
|
14 |
+
|
15 |
+
//remove cron jobs
|
16 |
+
wp_clear_scheduled_hook('truncate_sll');
|