Temporary Login Without Password - Version 1.0

Version Description

  • Initial Release
Download this release

Release Info

Developer storeapps
Plugin Icon 128x128 Temporary Login Without Password
Version 1.0
Comparing to
See all releases

Version 1.0

admin/class-wp-temporary-login-without-password-admin.php ADDED
@@ -0,0 +1,271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Wp_Temporary_Login_Without_Password_Admin {
4
+
5
+ private $plugin_name;
6
+ private $version;
7
+
8
+ public function __construct($plugin_name, $version) {
9
+
10
+ $this->plugin_name = $plugin_name;
11
+ $this->version = $version;
12
+ }
13
+
14
+ public function enqueue_styles() {
15
+ wp_enqueue_style($this->plugin_name, plugin_dir_url(__FILE__) . 'css/wp-temporary-login-without-password-admin.css', array(), $this->version, 'all');
16
+ }
17
+
18
+ public function enqueue_scripts() {
19
+ wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . 'js/wp-temporary-login-without-password-admin.js', array('jquery'), $this->version, false);
20
+ wp_enqueue_script('clipboardjs', plugin_dir_url(__FILE__) . 'js/clipboard.min.js', array('jquery'), $this->version, false);
21
+ }
22
+
23
+ public function admin_menu() {
24
+ $current_user_id = get_current_user_id();
25
+ if (!Wp_Temporary_Login_Without_Password_Common::is_valid_temporary_login($current_user_id)) {
26
+ add_users_page(__('Temporary Logins', Wp_Temporary_Login_Without_Password_i18n::$text_domain), __('Temporary Logins', Wp_Temporary_Login_Without_Password_i18n::$text_domain), apply_filters('tempadmin_user_cap', 'manage_options'), Wp_Temporary_Login_Without_Password_i18n::$text_domain, array(__class__, 'admin_settings'));
27
+ }
28
+ }
29
+
30
+ public static function admin_settings() {
31
+ $_template_file = WTLWP_PLUGIN_DIR . '/templates/admin_settings.php';
32
+ $wtlwp_generated_url = !empty($_REQUEST['wtlwp_generated_url']) ? $_REQUEST['wtlwp_generated_url'] : '';
33
+ $user_email = !empty($_REQUEST['user_email']) ? $_REQUEST['user_email'] : '';
34
+ include $_template_file;
35
+ }
36
+
37
+ public function create_user() {
38
+
39
+ if (empty($_POST['wtlwp_data']) || empty($_POST['wtlwp-nonce'])) {
40
+ return;
41
+ }
42
+
43
+ $data = $_POST['wtlwp_data'];
44
+ $email = $data['user_email'];
45
+ $error = false;
46
+
47
+ $redirect_link = '';
48
+ if (false == Wp_Temporary_Login_Without_Password_Common::can_manage_wtlwp()) {
49
+ $result = array('status' => 'error', 'message' => 'unathorised_access');
50
+ $error = true;
51
+ }else if (!wp_verify_nonce($_POST['wtlwp-nonce'], 'wtlwp_generate_login_url')) {
52
+ $result = array('status' => 'error', 'message' => 'nonce_failed');
53
+ $error = true;
54
+ }else if (empty($data['user_email'])) {
55
+ $result = array('status' => 'error', 'message' => 'empty_email');
56
+ $error = true;
57
+ }else if (!is_email($email)) {
58
+ $result = array('status' => 'error', 'message' => 'not_valid_email');
59
+ $error = true;
60
+ }else if (!empty($data['user_email']) && email_exists($data['user_email'])) {
61
+ $result = array('status' => 'error', 'message' => 'email_is_in_use');
62
+ $error = true;
63
+ }
64
+
65
+ if (!$error) {
66
+ $user = Wp_Temporary_Login_Without_Password_Common::create_new_user($data);
67
+ if (!empty($user['error'])) {
68
+ $result = array('status' => 'error', 'message' => 'user_creation_failed');
69
+ } else {
70
+ $result = array('status' => 'success', 'message' => 'user_created');
71
+ $redirect_link = Wp_Temporary_Login_Without_Password_Common::get_redirect_link($result);
72
+ $redirect_link = add_query_arg('wtlwp_generated_url', Wp_Temporary_Login_Without_Password_Common::get_login_url($user), $redirect_link);
73
+ $redirect_link = add_query_arg('user_email', $email, $redirect_link);
74
+ }
75
+ }
76
+
77
+ if(empty($redirect_link)) {
78
+ $redirect_link = Wp_Temporary_Login_Without_Password_Common::get_redirect_link($result);
79
+ }
80
+
81
+
82
+ wp_redirect($redirect_link, 302);
83
+ exit();
84
+ }
85
+
86
+ public static function delete_user() {
87
+
88
+ if ((false === Wp_Temporary_Login_Without_Password_Common::can_manage_wtlwp()) || empty($_REQUEST['wtlwp_action']) || ($_REQUEST['wtlwp_action'] != 'delete') || empty($_REQUEST['user_id']) || (absint($_REQUEST['user_id']) == 0)) {
89
+ return;
90
+ }
91
+
92
+ $user_id = absint($_REQUEST['user_id']);
93
+ $nonce = $_REQUEST['manage-temporary-login'];
94
+ $redirect_url = '';
95
+ $error = false;
96
+ if (!wp_verify_nonce($nonce, 'manage-temporary-login_' . $user_id)) {
97
+ $result = array('status' => 'error', 'message' => 'nonce_failed');
98
+ $error = true;
99
+ } else if(!Wp_Temporary_Login_Without_Password_Common::is_valid_temporary_login($user_id, false)) {
100
+ $result = array('status' => 'error', 'message' => 'is_not_temporary_login');
101
+ $error = true;
102
+ }
103
+
104
+ if (!$error) {
105
+ $delete_user = wp_delete_user(absint($user_id), get_current_user_id());
106
+ if (!is_wp_error($delete_user)) {
107
+ $result = array('status' => 'success', 'message' => 'user_deleted');
108
+ } else {
109
+ $result = array('status' => 'error', 'message' => 'default_error_message');
110
+ }
111
+ }
112
+
113
+ $redirect_url = Wp_Temporary_Login_Without_Password_Common::get_redirect_link($result);
114
+ wp_redirect($redirect_url, 302);
115
+ exit();
116
+ }
117
+
118
+ public static function manage_temporary_login() {
119
+
120
+ if ((false === Wp_Temporary_Login_Without_Password_Common::can_manage_wtlwp()) || empty($_REQUEST['wtlwp_action']) || ($_REQUEST['wtlwp_action'] != 'disable' && $_REQUEST['wtlwp_action'] != 'enable') || empty($_REQUEST['user_id']) || (absint($_REQUEST['user_id']) == 0)) {
121
+ return;
122
+ }
123
+
124
+ $error = false;
125
+ $user_id = absint($_REQUEST['user_id']);
126
+ $action = $_REQUEST['wtlwp_action'];
127
+ $nonce = $_REQUEST['manage-temporary-login'];
128
+
129
+ $is_valid_temporary_user = Wp_Temporary_Login_Without_Password_Common::is_valid_temporary_login($user_id, false);
130
+
131
+ if (!$is_valid_temporary_user) {
132
+ $result = array('status' => 'error', 'message' => 'is_not_temporary_login');
133
+ $error = true;
134
+ } else if (!wp_verify_nonce($nonce, 'manage-temporary-login_' . $user_id)) {
135
+ $result = array('status' => 'error', 'message' => 'nonce_failed');
136
+ $error = true;
137
+ }
138
+
139
+ if(!$error) {
140
+ if ($action == 'disable') {
141
+ $disable_login = Wp_Temporary_Login_Without_Password_Common::manage_login(absint($user_id), 'disable');
142
+ if ($disable_login) {
143
+ $result = array('status' => 'success', 'message' => 'login_disabled');
144
+ } else {
145
+ $result = array('status' => 'error', 'message' => 'default_error_message');
146
+ $error = true;
147
+ }
148
+ } else if ($action == 'enable') {
149
+ $enable_login = Wp_Temporary_Login_Without_Password_Common::manage_login(absint($user_id), 'enable');
150
+
151
+ if ($enable_login) {
152
+ $result = array('status' => 'success', 'message' => 'login_enabled');
153
+ } else {
154
+ $result = array('status' => 'error', 'message' => 'default_error_message');
155
+ $error = true;
156
+ }
157
+ } else {
158
+ $result = array('status' => 'error', 'message' => 'invalid_action');
159
+ $error = true;
160
+ }
161
+ }
162
+
163
+ $redirect_link = Wp_Temporary_Login_Without_Password_Common::get_redirect_link($result);
164
+ wp_redirect($redirect_link, 302);
165
+ exit();
166
+ }
167
+
168
+ public function display_admin_notices() {
169
+
170
+ if (empty($_REQUEST['page']) || (empty($_REQUEST['page']) && $_REQUEST['page'] !== 'wp-temporary-login-without-password') || !isset($_REQUEST['wtlwp_message']) || (!isset($_REQUEST['wtlwp_error']) && !isset($_REQUEST['wtlwp_success']))) {
171
+ return;
172
+ }
173
+
174
+ $class = $message = '';
175
+ $error = !empty($_REQUEST['wtlwp_error']) ? true : false;
176
+ $success = !empty($_REQUEST['wtlwp_success']) ? true : false;
177
+ if ($error) {
178
+ $message_type = !empty($_REQUEST['wtlwp_message']) ? $_REQUEST['wtlwp_message'] : 'default_error_message';
179
+ switch ($message_type) {
180
+ case 'user_creation_failed':
181
+ $message = __('User creation failed', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
182
+ break;
183
+
184
+ case 'unathorised_access':
185
+ $message = __('You do not have permission to create a temporary login', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
186
+ break;
187
+
188
+ case 'email_is_in_use':
189
+ $message = __('Email already is in use', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
190
+ break;
191
+
192
+ case 'empty_email':
193
+ $message = __('Please enter valid email address. Email field should not be empty', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
194
+ break;
195
+
196
+ case 'not_valid_email':
197
+ $message = __('Please enter valid email address', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
198
+ break;
199
+
200
+ case 'is_not_temporary_login':
201
+ $message = __('User you are trying to delete is not temporary', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
202
+ break;
203
+
204
+ case 'nonce_failed':
205
+ $message = __('Nonce failed', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
206
+ break;
207
+
208
+ case 'invalid_action':
209
+ $message = __('Invalid action', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
210
+ break;
211
+
212
+ case 'default_error_message':
213
+ default:
214
+ $message = __('Unknown error occured', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
215
+ break;
216
+ }
217
+ $class = 'error';
218
+ } else if ($success) {
219
+ $message_type = !empty($_REQUEST['wtlwp_message']) ? $_REQUEST['wtlwp_message'] : 'default_success_message';
220
+ switch ($message_type) {
221
+ case 'user_created':
222
+ $message = __('Login created successfully!', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
223
+ break;
224
+
225
+ case 'user_deleted':
226
+ $message = __('Login deleted successfully!', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
227
+ break;
228
+
229
+ case 'login_disabled':
230
+ $message = __('Login disabled successfully!', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
231
+ break;
232
+
233
+ case 'login_enabled':
234
+ $message = __('Login enabled successfully!', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
235
+ break;
236
+
237
+ default:
238
+ $message = __('Success!', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
239
+ break;
240
+ }
241
+
242
+ $class = 'updated';
243
+ }
244
+
245
+
246
+ $class .= ' notice notice-succe is-dismissible';
247
+
248
+ if (!empty($message)) {
249
+ $notice = '';
250
+ $notice .= '<div id="notice" class="' . $class . '">';
251
+ $notice .= '<p>' . esc_attr($message) . '</p>';
252
+ $notice .= '</div>';
253
+
254
+ echo $notice;
255
+ }
256
+
257
+ return;
258
+ }
259
+
260
+ public function disable_welcome_notification($blog_id, $user_id, $password, $title, $meta) {
261
+
262
+ if (!empty($user_id)) {
263
+ if (Wp_Temporary_Login_Without_Password_Common::is_valid_temporary_login($user_id)) {
264
+ return false;
265
+ }
266
+ }
267
+
268
+ return true;
269
+ }
270
+
271
+ }
admin/css/wp-temporary-login-without-password-admin.css ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .new-wtlwp-form {
2
+ border: 1px solid;
3
+ padding: 10px;
4
+ background-color: white;
5
+ display: none;
6
+ }
7
+
8
+ .wtlwp-form-input {
9
+ width: 300px !important;
10
+ }
11
+ .widefat .wtlwp-status {
12
+ width: 40px;
13
+ }
14
+
15
+ .wtlwp-status-active {
16
+ color: #008000 !important;
17
+ }
18
+
19
+ .wtlwp-status-expired {
20
+ color: #FF0000 !important;
21
+ }
22
+
23
+ .wtlwp-status:after {
24
+ border-radius: 32px;
25
+ color: #fff;
26
+ display: block;
27
+ font-size: 11px;
28
+ font-weight: bold;
29
+ height: 16px;
30
+ line-height: 17px;
31
+ margin-left: 8px;
32
+ text-align: center;
33
+ width: 16px;
34
+ }
35
+
36
+ .wtlwp-status-active:after {
37
+ background: #008000 none repeat scroll 0 0;
38
+ content: "";
39
+ }
40
+
41
+ .wtlwp-status-expired:after {
42
+ background: #FF0000 none repeat scroll 0 0;
43
+ content: "";
44
+ }
45
+
46
+ .cancel-new-login-form {
47
+ cursor: pointer;
48
+ }
49
+
50
+ .wtlwp-wide-input {
51
+ width: 60%;
52
+ }
53
+
54
+ .generated-wtlwp-login-link {
55
+ border: 1px solid;
56
+ padding: 10px 10px 10px 10px;
57
+ }
58
+
59
+ .wtlwp-form-row {
60
+ padding-left: 20px !important;
61
+ }
62
+
63
+ .wtlwp-form-submit-button {
64
+ width: 115px;
65
+ }
66
+
67
+ .wtlwp-user-login {
68
+ font-size: 12px;
69
+ }
70
+
71
+ .wtlwp-copy-to-clipboard, .wtlwp-click-to-copy-btn {
72
+ cursor: pointer;
73
+ }
74
+
75
+ .wtlwp-copy-to-clipboard:hover {
76
+ color: #0073aa;
77
+ }
78
+
79
+ .copied-text-message {
80
+ padding: 20px;
81
+ }
admin/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden
admin/js/clipboard.js ADDED
@@ -0,0 +1,742 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * clipboard.js v1.5.12
3
+ * https://zenorocha.github.io/clipboard.js
4
+ *
5
+ * Licensed MIT © Zeno Rocha
6
+ */
7
+ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Clipboard = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
8
+ var matches = require('matches-selector')
9
+
10
+ module.exports = function (element, selector, checkYoSelf) {
11
+ var parent = checkYoSelf ? element : element.parentNode
12
+
13
+ while (parent && parent !== document) {
14
+ if (matches(parent, selector)) return parent;
15
+ parent = parent.parentNode
16
+ }
17
+ }
18
+
19
+ },{"matches-selector":5}],2:[function(require,module,exports){
20
+ var closest = require('closest');
21
+
22
+ /**
23
+ * Delegates event to a selector.
24
+ *
25
+ * @param {Element} element
26
+ * @param {String} selector
27
+ * @param {String} type
28
+ * @param {Function} callback
29
+ * @param {Boolean} useCapture
30
+ * @return {Object}
31
+ */
32
+ function delegate(element, selector, type, callback, useCapture) {
33
+ var listenerFn = listener.apply(this, arguments);
34
+
35
+ element.addEventListener(type, listenerFn, useCapture);
36
+
37
+ return {
38
+ destroy: function() {
39
+ element.removeEventListener(type, listenerFn, useCapture);
40
+ }
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Finds closest match and invokes callback.
46
+ *
47
+ * @param {Element} element
48
+ * @param {String} selector
49
+ * @param {String} type
50
+ * @param {Function} callback
51
+ * @return {Function}
52
+ */
53
+ function listener(element, selector, type, callback) {
54
+ return function(e) {
55
+ e.delegateTarget = closest(e.target, selector, true);
56
+
57
+ if (e.delegateTarget) {
58
+ callback.call(element, e);
59
+ }
60
+ }
61
+ }
62
+
63
+ module.exports = delegate;
64
+
65
+ },{"closest":1}],3:[function(require,module,exports){
66
+ /**
67
+ * Check if argument is a HTML element.
68
+ *
69
+ * @param {Object} value
70
+ * @return {Boolean}
71
+ */
72
+ exports.node = function(value) {
73
+ return value !== undefined
74
+ && value instanceof HTMLElement
75
+ && value.nodeType === 1;
76
+ };
77
+
78
+ /**
79
+ * Check if argument is a list of HTML elements.
80
+ *
81
+ * @param {Object} value
82
+ * @return {Boolean}
83
+ */
84
+ exports.nodeList = function(value) {
85
+ var type = Object.prototype.toString.call(value);
86
+
87
+ return value !== undefined
88
+ && (type === '[object NodeList]' || type === '[object HTMLCollection]')
89
+ && ('length' in value)
90
+ && (value.length === 0 || exports.node(value[0]));
91
+ };
92
+
93
+ /**
94
+ * Check if argument is a string.
95
+ *
96
+ * @param {Object} value
97
+ * @return {Boolean}
98
+ */
99
+ exports.string = function(value) {
100
+ return typeof value === 'string'
101
+ || value instanceof String;
102
+ };
103
+
104
+ /**
105
+ * Check if argument is a function.
106
+ *
107
+ * @param {Object} value
108
+ * @return {Boolean}
109
+ */
110
+ exports.fn = function(value) {
111
+ var type = Object.prototype.toString.call(value);
112
+
113
+ return type === '[object Function]';
114
+ };
115
+
116
+ },{}],4:[function(require,module,exports){
117
+ var is = require('./is');
118
+ var delegate = require('delegate');
119
+
120
+ /**
121
+ * Validates all params and calls the right
122
+ * listener function based on its target type.
123
+ *
124
+ * @param {String|HTMLElement|HTMLCollection|NodeList} target
125
+ * @param {String} type
126
+ * @param {Function} callback
127
+ * @return {Object}
128
+ */
129
+ function listen(target, type, callback) {
130
+ if (!target && !type && !callback) {
131
+ throw new Error('Missing required arguments');
132
+ }
133
+
134
+ if (!is.string(type)) {
135
+ throw new TypeError('Second argument must be a String');
136
+ }
137
+
138
+ if (!is.fn(callback)) {
139
+ throw new TypeError('Third argument must be a Function');
140
+ }
141
+
142
+ if (is.node(target)) {
143
+ return listenNode(target, type, callback);
144
+ }
145
+ else if (is.nodeList(target)) {
146
+ return listenNodeList(target, type, callback);
147
+ }
148
+ else if (is.string(target)) {
149
+ return listenSelector(target, type, callback);
150
+ }
151
+ else {
152
+ throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Adds an event listener to a HTML element
158
+ * and returns a remove listener function.
159
+ *
160
+ * @param {HTMLElement} node
161
+ * @param {String} type
162
+ * @param {Function} callback
163
+ * @return {Object}
164
+ */
165
+ function listenNode(node, type, callback) {
166
+ node.addEventListener(type, callback);
167
+
168
+ return {
169
+ destroy: function() {
170
+ node.removeEventListener(type, callback);
171
+ }
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Add an event listener to a list of HTML elements
177
+ * and returns a remove listener function.
178
+ *
179
+ * @param {NodeList|HTMLCollection} nodeList
180
+ * @param {String} type
181
+ * @param {Function} callback
182
+ * @return {Object}
183
+ */
184
+ function listenNodeList(nodeList, type, callback) {
185
+ Array.prototype.forEach.call(nodeList, function(node) {
186
+ node.addEventListener(type, callback);
187
+ });
188
+
189
+ return {
190
+ destroy: function() {
191
+ Array.prototype.forEach.call(nodeList, function(node) {
192
+ node.removeEventListener(type, callback);
193
+ });
194
+ }
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Add an event listener to a selector
200
+ * and returns a remove listener function.
201
+ *
202
+ * @param {String} selector
203
+ * @param {String} type
204
+ * @param {Function} callback
205
+ * @return {Object}
206
+ */
207
+ function listenSelector(selector, type, callback) {
208
+ return delegate(document.body, selector, type, callback);
209
+ }
210
+
211
+ module.exports = listen;
212
+
213
+ },{"./is":3,"delegate":2}],5:[function(require,module,exports){
214
+
215
+ /**
216
+ * Element prototype.
217
+ */
218
+
219
+ var proto = Element.prototype;
220
+
221
+ /**
222
+ * Vendor function.
223
+ */
224
+
225
+ var vendor = proto.matchesSelector
226
+ || proto.webkitMatchesSelector
227
+ || proto.mozMatchesSelector
228
+ || proto.msMatchesSelector
229
+ || proto.oMatchesSelector;
230
+
231
+ /**
232
+ * Expose `match()`.
233
+ */
234
+
235
+ module.exports = match;
236
+
237
+ /**
238
+ * Match `el` to `selector`.
239
+ *
240
+ * @param {Element} el
241
+ * @param {String} selector
242
+ * @return {Boolean}
243
+ * @api public
244
+ */
245
+
246
+ function match(el, selector) {
247
+ if (vendor) return vendor.call(el, selector);
248
+ var nodes = el.parentNode.querySelectorAll(selector);
249
+ for (var i = 0; i < nodes.length; ++i) {
250
+ if (nodes[i] == el) return true;
251
+ }
252
+ return false;
253
+ }
254
+ },{}],6:[function(require,module,exports){
255
+ function select(element) {
256
+ var selectedText;
257
+
258
+ if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
259
+ element.focus();
260
+ element.setSelectionRange(0, element.value.length);
261
+
262
+ selectedText = element.value;
263
+ }
264
+ else {
265
+ if (element.hasAttribute('contenteditable')) {
266
+ element.focus();
267
+ }
268
+
269
+ var selection = window.getSelection();
270
+ var range = document.createRange();
271
+
272
+ range.selectNodeContents(element);
273
+ selection.removeAllRanges();
274
+ selection.addRange(range);
275
+
276
+ selectedText = selection.toString();
277
+ }
278
+
279
+ return selectedText;
280
+ }
281
+
282
+ module.exports = select;
283
+
284
+ },{}],7:[function(require,module,exports){
285
+ function E () {
286
+ // Keep this empty so it's easier to inherit from
287
+ // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
288
+ }
289
+
290
+ E.prototype = {
291
+ on: function (name, callback, ctx) {
292
+ var e = this.e || (this.e = {});
293
+
294
+ (e[name] || (e[name] = [])).push({
295
+ fn: callback,
296
+ ctx: ctx
297
+ });
298
+
299
+ return this;
300
+ },
301
+
302
+ once: function (name, callback, ctx) {
303
+ var self = this;
304
+ function listener () {
305
+ self.off(name, listener);
306
+ callback.apply(ctx, arguments);
307
+ };
308
+
309
+ listener._ = callback
310
+ return this.on(name, listener, ctx);
311
+ },
312
+
313
+ emit: function (name) {
314
+ var data = [].slice.call(arguments, 1);
315
+ var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
316
+ var i = 0;
317
+ var len = evtArr.length;
318
+
319
+ for (i; i < len; i++) {
320
+ evtArr[i].fn.apply(evtArr[i].ctx, data);
321
+ }
322
+
323
+ return this;
324
+ },
325
+
326
+ off: function (name, callback) {
327
+ var e = this.e || (this.e = {});
328
+ var evts = e[name];
329
+ var liveEvents = [];
330
+
331
+ if (evts && callback) {
332
+ for (var i = 0, len = evts.length; i < len; i++) {
333
+ if (evts[i].fn !== callback && evts[i].fn._ !== callback)
334
+ liveEvents.push(evts[i]);
335
+ }
336
+ }
337
+
338
+ // Remove event from queue to prevent memory leak
339
+ // Suggested by https://github.com/lazd
340
+ // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910
341
+
342
+ (liveEvents.length)
343
+ ? e[name] = liveEvents
344
+ : delete e[name];
345
+
346
+ return this;
347
+ }
348
+ };
349
+
350
+ module.exports = E;
351
+
352
+ },{}],8:[function(require,module,exports){
353
+ (function (global, factory) {
354
+ if (typeof define === "function" && define.amd) {
355
+ define(['module', 'select'], factory);
356
+ } else if (typeof exports !== "undefined") {
357
+ factory(module, require('select'));
358
+ } else {
359
+ var mod = {
360
+ exports: {}
361
+ };
362
+ factory(mod, global.select);
363
+ global.clipboardAction = mod.exports;
364
+ }
365
+ })(this, function (module, _select) {
366
+ 'use strict';
367
+
368
+ var _select2 = _interopRequireDefault(_select);
369
+
370
+ function _interopRequireDefault(obj) {
371
+ return obj && obj.__esModule ? obj : {
372
+ default: obj
373
+ };
374
+ }
375
+
376
+ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
377
+ return typeof obj;
378
+ } : function (obj) {
379
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;
380
+ };
381
+
382
+ function _classCallCheck(instance, Constructor) {
383
+ if (!(instance instanceof Constructor)) {
384
+ throw new TypeError("Cannot call a class as a function");
385
+ }
386
+ }
387
+
388
+ var _createClass = function () {
389
+ function defineProperties(target, props) {
390
+ for (var i = 0; i < props.length; i++) {
391
+ var descriptor = props[i];
392
+ descriptor.enumerable = descriptor.enumerable || false;
393
+ descriptor.configurable = true;
394
+ if ("value" in descriptor) descriptor.writable = true;
395
+ Object.defineProperty(target, descriptor.key, descriptor);
396
+ }
397
+ }
398
+
399
+ return function (Constructor, protoProps, staticProps) {
400
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
401
+ if (staticProps) defineProperties(Constructor, staticProps);
402
+ return Constructor;
403
+ };
404
+ }();
405
+
406
+ var ClipboardAction = function () {
407
+ /**
408
+ * @param {Object} options
409
+ */
410
+
411
+ function ClipboardAction(options) {
412
+ _classCallCheck(this, ClipboardAction);
413
+
414
+ this.resolveOptions(options);
415
+ this.initSelection();
416
+ }
417
+
418
+ /**
419
+ * Defines base properties passed from constructor.
420
+ * @param {Object} options
421
+ */
422
+
423
+
424
+ ClipboardAction.prototype.resolveOptions = function resolveOptions() {
425
+ var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
426
+
427
+ this.action = options.action;
428
+ this.emitter = options.emitter;
429
+ this.target = options.target;
430
+ this.text = options.text;
431
+ this.trigger = options.trigger;
432
+
433
+ this.selectedText = '';
434
+ };
435
+
436
+ ClipboardAction.prototype.initSelection = function initSelection() {
437
+ if (this.text) {
438
+ this.selectFake();
439
+ } else if (this.target) {
440
+ this.selectTarget();
441
+ }
442
+ };
443
+
444
+ ClipboardAction.prototype.selectFake = function selectFake() {
445
+ var _this = this;
446
+
447
+ var isRTL = document.documentElement.getAttribute('dir') == 'rtl';
448
+
449
+ this.removeFake();
450
+
451
+ this.fakeHandlerCallback = function () {
452
+ return _this.removeFake();
453
+ };
454
+ this.fakeHandler = document.body.addEventListener('click', this.fakeHandlerCallback) || true;
455
+
456
+ this.fakeElem = document.createElement('textarea');
457
+ // Prevent zooming on iOS
458
+ this.fakeElem.style.fontSize = '12pt';
459
+ // Reset box model
460
+ this.fakeElem.style.border = '0';
461
+ this.fakeElem.style.padding = '0';
462
+ this.fakeElem.style.margin = '0';
463
+ // Move element out of screen horizontally
464
+ this.fakeElem.style.position = 'absolute';
465
+ this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';
466
+ // Move element to the same position vertically
467
+ this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
468
+ this.fakeElem.setAttribute('readonly', '');
469
+ this.fakeElem.value = this.text;
470
+
471
+ document.body.appendChild(this.fakeElem);
472
+
473
+ this.selectedText = (0, _select2.default)(this.fakeElem);
474
+ this.copyText();
475
+ };
476
+
477
+ ClipboardAction.prototype.removeFake = function removeFake() {
478
+ if (this.fakeHandler) {
479
+ document.body.removeEventListener('click', this.fakeHandlerCallback);
480
+ this.fakeHandler = null;
481
+ this.fakeHandlerCallback = null;
482
+ }
483
+
484
+ if (this.fakeElem) {
485
+ document.body.removeChild(this.fakeElem);
486
+ this.fakeElem = null;
487
+ }
488
+ };
489
+
490
+ ClipboardAction.prototype.selectTarget = function selectTarget() {
491
+ this.selectedText = (0, _select2.default)(this.target);
492
+ this.copyText();
493
+ };
494
+
495
+ ClipboardAction.prototype.copyText = function copyText() {
496
+ var succeeded = undefined;
497
+
498
+ try {
499
+ succeeded = document.execCommand(this.action);
500
+ } catch (err) {
501
+ succeeded = false;
502
+ }
503
+
504
+ this.handleResult(succeeded);
505
+ };
506
+
507
+ ClipboardAction.prototype.handleResult = function handleResult(succeeded) {
508
+ if (succeeded) {
509
+ this.emitter.emit('success', {
510
+ action: this.action,
511
+ text: this.selectedText,
512
+ trigger: this.trigger,
513
+ clearSelection: this.clearSelection.bind(this)
514
+ });
515
+ } else {
516
+ this.emitter.emit('error', {
517
+ action: this.action,
518
+ trigger: this.trigger,
519
+ clearSelection: this.clearSelection.bind(this)
520
+ });
521
+ }
522
+ };
523
+
524
+ ClipboardAction.prototype.clearSelection = function clearSelection() {
525
+ if (this.target) {
526
+ this.target.blur();
527
+ }
528
+
529
+ window.getSelection().removeAllRanges();
530
+ };
531
+
532
+ ClipboardAction.prototype.destroy = function destroy() {
533
+ this.removeFake();
534
+ };
535
+
536
+ _createClass(ClipboardAction, [{
537
+ key: 'action',
538
+ set: function set() {
539
+ var action = arguments.length <= 0 || arguments[0] === undefined ? 'copy' : arguments[0];
540
+
541
+ this._action = action;
542
+
543
+ if (this._action !== 'copy' && this._action !== 'cut') {
544
+ throw new Error('Invalid "action" value, use either "copy" or "cut"');
545
+ }
546
+ },
547
+ get: function get() {
548
+ return this._action;
549
+ }
550
+ }, {
551
+ key: 'target',
552
+ set: function set(target) {
553
+ if (target !== undefined) {
554
+ if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) {
555
+ if (this.action === 'copy' && target.hasAttribute('disabled')) {
556
+ throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');
557
+ }
558
+
559
+ if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {
560
+ throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');
561
+ }
562
+
563
+ this._target = target;
564
+ } else {
565
+ throw new Error('Invalid "target" value, use a valid Element');
566
+ }
567
+ }
568
+ },
569
+ get: function get() {
570
+ return this._target;
571
+ }
572
+ }]);
573
+
574
+ return ClipboardAction;
575
+ }();
576
+
577
+ module.exports = ClipboardAction;
578
+ });
579
+
580
+ },{"select":6}],9:[function(require,module,exports){
581
+ (function (global, factory) {
582
+ if (typeof define === "function" && define.amd) {
583
+ define(['module', './clipboard-action', 'tiny-emitter', 'good-listener'], factory);
584
+ } else if (typeof exports !== "undefined") {
585
+ factory(module, require('./clipboard-action'), require('tiny-emitter'), require('good-listener'));
586
+ } else {
587
+ var mod = {
588
+ exports: {}
589
+ };
590
+ factory(mod, global.clipboardAction, global.tinyEmitter, global.goodListener);
591
+ global.clipboard = mod.exports;
592
+ }
593
+ })(this, function (module, _clipboardAction, _tinyEmitter, _goodListener) {
594
+ 'use strict';
595
+
596
+ var _clipboardAction2 = _interopRequireDefault(_clipboardAction);
597
+
598
+ var _tinyEmitter2 = _interopRequireDefault(_tinyEmitter);
599
+
600
+ var _goodListener2 = _interopRequireDefault(_goodListener);
601
+
602
+ function _interopRequireDefault(obj) {
603
+ return obj && obj.__esModule ? obj : {
604
+ default: obj
605
+ };
606
+ }
607
+
608
+ function _classCallCheck(instance, Constructor) {
609
+ if (!(instance instanceof Constructor)) {
610
+ throw new TypeError("Cannot call a class as a function");
611
+ }
612
+ }
613
+
614
+ function _possibleConstructorReturn(self, call) {
615
+ if (!self) {
616
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
617
+ }
618
+
619
+ return call && (typeof call === "object" || typeof call === "function") ? call : self;
620
+ }
621
+
622
+ function _inherits(subClass, superClass) {
623
+ if (typeof superClass !== "function" && superClass !== null) {
624
+ throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
625
+ }
626
+
627
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
628
+ constructor: {
629
+ value: subClass,
630
+ enumerable: false,
631
+ writable: true,
632
+ configurable: true
633
+ }
634
+ });
635
+ if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
636
+ }
637
+
638
+ var Clipboard = function (_Emitter) {
639
+ _inherits(Clipboard, _Emitter);
640
+
641
+ /**
642
+ * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
643
+ * @param {Object} options
644
+ */
645
+
646
+ function Clipboard(trigger, options) {
647
+ _classCallCheck(this, Clipboard);
648
+
649
+ var _this = _possibleConstructorReturn(this, _Emitter.call(this));
650
+
651
+ _this.resolveOptions(options);
652
+ _this.listenClick(trigger);
653
+ return _this;
654
+ }
655
+
656
+ /**
657
+ * Defines if attributes would be resolved using internal setter functions
658
+ * or custom functions that were passed in the constructor.
659
+ * @param {Object} options
660
+ */
661
+
662
+
663
+ Clipboard.prototype.resolveOptions = function resolveOptions() {
664
+ var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
665
+
666
+ this.action = typeof options.action === 'function' ? options.action : this.defaultAction;
667
+ this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;
668
+ this.text = typeof options.text === 'function' ? options.text : this.defaultText;
669
+ };
670
+
671
+ Clipboard.prototype.listenClick = function listenClick(trigger) {
672
+ var _this2 = this;
673
+
674
+ this.listener = (0, _goodListener2.default)(trigger, 'click', function (e) {
675
+ return _this2.onClick(e);
676
+ });
677
+ };
678
+
679
+ Clipboard.prototype.onClick = function onClick(e) {
680
+ var trigger = e.delegateTarget || e.currentTarget;
681
+
682
+ if (this.clipboardAction) {
683
+ this.clipboardAction = null;
684
+ }
685
+
686
+ this.clipboardAction = new _clipboardAction2.default({
687
+ action: this.action(trigger),
688
+ target: this.target(trigger),
689
+ text: this.text(trigger),
690
+ trigger: trigger,
691
+ emitter: this
692
+ });
693
+ };
694
+
695
+ Clipboard.prototype.defaultAction = function defaultAction(trigger) {
696
+ return getAttributeValue('action', trigger);
697
+ };
698
+
699
+ Clipboard.prototype.defaultTarget = function defaultTarget(trigger) {
700
+ var selector = getAttributeValue('target', trigger);
701
+
702
+ if (selector) {
703
+ return document.querySelector(selector);
704
+ }
705
+ };
706
+
707
+ Clipboard.prototype.defaultText = function defaultText(trigger) {
708
+ return getAttributeValue('text', trigger);
709
+ };
710
+
711
+ Clipboard.prototype.destroy = function destroy() {
712
+ this.listener.destroy();
713
+
714
+ if (this.clipboardAction) {
715
+ this.clipboardAction.destroy();
716
+ this.clipboardAction = null;
717
+ }
718
+ };
719
+
720
+ return Clipboard;
721
+ }(_tinyEmitter2.default);
722
+
723
+ /**
724
+ * Helper function to retrieve attribute value.
725
+ * @param {String} suffix
726
+ * @param {Element} element
727
+ */
728
+ function getAttributeValue(suffix, element) {
729
+ var attribute = 'data-clipboard-' + suffix;
730
+
731
+ if (!element.hasAttribute(attribute)) {
732
+ return;
733
+ }
734
+
735
+ return element.getAttribute(attribute);
736
+ }
737
+
738
+ module.exports = Clipboard;
739
+ });
740
+
741
+ },{"./clipboard-action":8,"good-listener":4,"tiny-emitter":7}]},{},[9])(9)
742
+ });
admin/js/clipboard.min.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /*!
2
+ * clipboard.js v1.5.12
3
+ * https://zenorocha.github.io/clipboard.js
4
+ *
5
+ * Licensed MIT © Zeno Rocha
6
+ */
7
+ !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,o){function i(a,c){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!c&&s)return s(a,!0);if(r)return r(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var u=n[a]={exports:{}};e[a][0].call(u.exports,function(t){var n=e[a][1][t];return i(n?n:t)},u,u.exports,t,e,n,o)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;a<o.length;a++)i(o[a]);return i}({1:[function(t,e,n){var o=t("matches-selector");e.exports=function(t,e,n){for(var i=n?t:t.parentNode;i&&i!==document;){if(o(i,e))return i;i=i.parentNode}}},{"matches-selector":5}],2:[function(t,e,n){function o(t,e,n,o,r){var a=i.apply(this,arguments);return t.addEventListener(n,a,r),{destroy:function(){t.removeEventListener(n,a,r)}}}function i(t,e,n,o){return function(n){n.delegateTarget=r(n.target,e,!0),n.delegateTarget&&o.call(t,n)}}var r=t("closest");e.exports=o},{closest:1}],3:[function(t,e,n){n.node=function(t){return void 0!==t&&t instanceof HTMLElement&&1===t.nodeType},n.nodeList=function(t){var e=Object.prototype.toString.call(t);return void 0!==t&&("[object NodeList]"===e||"[object HTMLCollection]"===e)&&"length"in t&&(0===t.length||n.node(t[0]))},n.string=function(t){return"string"==typeof t||t instanceof String},n.fn=function(t){var e=Object.prototype.toString.call(t);return"[object Function]"===e}},{}],4:[function(t,e,n){function o(t,e,n){if(!t&&!e&&!n)throw new Error("Missing required arguments");if(!c.string(e))throw new TypeError("Second argument must be a String");if(!c.fn(n))throw new TypeError("Third argument must be a Function");if(c.node(t))return i(t,e,n);if(c.nodeList(t))return r(t,e,n);if(c.string(t))return a(t,e,n);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function i(t,e,n){return t.addEventListener(e,n),{destroy:function(){t.removeEventListener(e,n)}}}function r(t,e,n){return Array.prototype.forEach.call(t,function(t){t.addEventListener(e,n)}),{destroy:function(){Array.prototype.forEach.call(t,function(t){t.removeEventListener(e,n)})}}}function a(t,e,n){return s(document.body,t,e,n)}var c=t("./is"),s=t("delegate");e.exports=o},{"./is":3,delegate:2}],5:[function(t,e,n){function o(t,e){if(r)return r.call(t,e);for(var n=t.parentNode.querySelectorAll(e),o=0;o<n.length;++o)if(n[o]==t)return!0;return!1}var i=Element.prototype,r=i.matchesSelector||i.webkitMatchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector;e.exports=o},{}],6:[function(t,e,n){function o(t){var e;if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName)t.focus(),t.setSelectionRange(0,t.value.length),e=t.value;else{t.hasAttribute("contenteditable")&&t.focus();var n=window.getSelection(),o=document.createRange();o.selectNodeContents(t),n.removeAllRanges(),n.addRange(o),e=n.toString()}return e}e.exports=o},{}],7:[function(t,e,n){function o(){}o.prototype={on:function(t,e,n){var o=this.e||(this.e={});return(o[t]||(o[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){function o(){i.off(t,o),e.apply(n,arguments)}var i=this;return o._=e,this.on(t,o,n)},emit:function(t){var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),o=0,i=n.length;for(o;i>o;o++)n[o].fn.apply(n[o].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),o=n[t],i=[];if(o&&e)for(var r=0,a=o.length;a>r;r++)o[r].fn!==e&&o[r].fn._!==e&&i.push(o[r]);return i.length?n[t]=i:delete n[t],this}},e.exports=o},{}],8:[function(e,n,o){!function(i,r){if("function"==typeof t&&t.amd)t(["module","select"],r);else if("undefined"!=typeof o)r(n,e("select"));else{var a={exports:{}};r(a,i.select),i.clipboardAction=a.exports}}(this,function(t,e){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var i=n(e),r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},a=function(){function t(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(e,n,o){return n&&t(e.prototype,n),o&&t(e,o),e}}(),c=function(){function t(e){o(this,t),this.resolveOptions(e),this.initSelection()}return t.prototype.resolveOptions=function t(){var e=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.action=e.action,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""},t.prototype.initSelection=function t(){this.text?this.selectFake():this.target&&this.selectTarget()},t.prototype.selectFake=function t(){var e=this,n="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=document.body.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[n?"right":"left"]="-9999px",this.fakeElem.style.top=(window.pageYOffset||document.documentElement.scrollTop)+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,document.body.appendChild(this.fakeElem),this.selectedText=(0,i.default)(this.fakeElem),this.copyText()},t.prototype.removeFake=function t(){this.fakeHandler&&(document.body.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(document.body.removeChild(this.fakeElem),this.fakeElem=null)},t.prototype.selectTarget=function t(){this.selectedText=(0,i.default)(this.target),this.copyText()},t.prototype.copyText=function t(){var e=void 0;try{e=document.execCommand(this.action)}catch(n){e=!1}this.handleResult(e)},t.prototype.handleResult=function t(e){e?this.emitter.emit("success",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)}):this.emitter.emit("error",{action:this.action,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})},t.prototype.clearSelection=function t(){this.target&&this.target.blur(),window.getSelection().removeAllRanges()},t.prototype.destroy=function t(){this.removeFake()},a(t,[{key:"action",set:function t(){var e=arguments.length<=0||void 0===arguments[0]?"copy":arguments[0];if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function t(){return this._action}},{key:"target",set:function t(e){if(void 0!==e){if(!e||"object"!==("undefined"==typeof e?"undefined":r(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function t(){return this._target}}]),t}();t.exports=c})},{select:6}],9:[function(e,n,o){!function(i,r){if("function"==typeof t&&t.amd)t(["module","./clipboard-action","tiny-emitter","good-listener"],r);else if("undefined"!=typeof o)r(n,e("./clipboard-action"),e("tiny-emitter"),e("good-listener"));else{var a={exports:{}};r(a,i.clipboardAction,i.tinyEmitter,i.goodListener),i.clipboard=a.exports}}(this,function(t,e,n,o){"use strict";function i(t){return t&&t.__esModule?t:{"default":t}}function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function c(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}var l=i(e),u=i(n),f=i(o),d=function(t){function e(n,o){r(this,e);var i=a(this,t.call(this));return i.resolveOptions(o),i.listenClick(n),i}return c(e,t),e.prototype.resolveOptions=function t(){var e=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText},e.prototype.listenClick=function t(e){var n=this;this.listener=(0,f.default)(e,"click",function(t){return n.onClick(t)})},e.prototype.onClick=function t(e){var n=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new l.default({action:this.action(n),target:this.target(n),text:this.text(n),trigger:n,emitter:this})},e.prototype.defaultAction=function t(e){return s("action",e)},e.prototype.defaultTarget=function t(e){var n=s("target",e);return n?document.querySelector(n):void 0},e.prototype.defaultText=function t(e){return s("text",e)},e.prototype.destroy=function t(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)},e}(u.default);t.exports=d})},{"./clipboard-action":8,"good-listener":4,"tiny-emitter":7}]},{},[9])(9)});
admin/js/wp-temporary-login-without-password-admin.js ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function ($) {
2
+ 'use strict';
3
+
4
+ jQuery(document).ready(function () {
5
+ //jQuery('#new-wtlwp-form').hide();
6
+
7
+ jQuery('#add-new-wtlwp-form-button').click(function () {
8
+ jQuery('#new-wtlwp-form').show();
9
+ });
10
+
11
+ jQuery('#cancel-new-login-form').click(function () {
12
+ jQuery('#new-wtlwp-form').hide();
13
+ });
14
+
15
+ if (jQuery('.wtlwp-click-to-copy-btn').get(0)) {
16
+
17
+ var clipboard = new Clipboard('.wtlwp-click-to-copy-btn');
18
+
19
+ clipboard.on('success', function (e) {
20
+ var elem = e.trigger;
21
+ var className = elem.getAttribute('class');
22
+ jQuery('#copied-text-message-' + className).text('Copied').fadeIn();
23
+ jQuery('#copied-text-message-' + className).fadeOut('slow');
24
+ });
25
+ }
26
+
27
+ if (jQuery('.wtlwp-copy-to-clipboard').get(0)) {
28
+ var clipboard_link = new Clipboard('.wtlwp-copy-to-clipboard');
29
+
30
+ clipboard_link.on('success', function (e) {
31
+ var elem = e.trigger;
32
+ var id = elem.getAttribute('id');
33
+ jQuery('#copied-' + id).text('Copied').fadeIn();
34
+ jQuery('#copied-' + id).fadeOut('slow');
35
+ });
36
+ }
37
+ });
38
+ })(jQuery);
includes/class-wp-temporary-login-without-password-common.php ADDED
@@ -0,0 +1,442 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Wp_Temporary_Login_Without_Password_Common {
4
+
5
+ public static function create_username($data) {
6
+
7
+ $first_name = isset($data['user_first_name']) ? $data['user_first_name'] : '';
8
+ $last_name = isset($data['user_last_name']) ? $data['user_last_name'] : '';
9
+ $email = isset($data['user_email']) ? $data['user_email'] : '';
10
+
11
+ $name = '';
12
+ if (!empty($first_name) || !empty($last_name)) {
13
+ $name = str_replace(array('.', '+'), '', trim($first_name . $last_name));
14
+ } else {
15
+ if (!empty($email)) {
16
+ $explode = explode('@', $email);
17
+ $name = str_replace(array('.', '+'), '', $explode[0]);
18
+ }
19
+ }
20
+
21
+ if (username_exists($name)) {
22
+ $name = $name . substr(uniqid('', true), -6);
23
+ }
24
+
25
+ return sanitize_user($name, true);
26
+ }
27
+
28
+ public static function create_new_user($data) {
29
+
30
+ if (false === Wp_Temporary_Login_Without_Password_Common::can_manage_wtlwp()) {
31
+ return;
32
+ }
33
+
34
+ $time = !empty($data['expiry']) ? $data['expiry'] : 'day';
35
+
36
+ $password = Wp_Temporary_Login_Without_Password_Common::generate_password();
37
+ $username = Wp_Temporary_Login_Without_Password_Common::create_username($data);
38
+ $first_name = isset($data['user_first_name']) ? sanitize_text_field($data['user_first_name']) : '';
39
+ $last_name = isset($data['user_last_name']) ? sanitize_text_field($data['user_last_name']) : '';
40
+ $email = isset($data['user_email']) ? sanitize_email($data['user_email']) : '';
41
+ $user_args = array(
42
+ 'first_name' => $first_name,
43
+ 'last_name' => $last_name,
44
+ 'user_login' => $username,
45
+ 'user_pass' => $password,
46
+ 'user_email' => sanitize_email($email, true),
47
+ 'role' => $data['role'],
48
+ );
49
+
50
+ $user_id = wp_insert_user($user_args);
51
+
52
+ if (is_wp_error($user_id)) {
53
+ $code = $user_id->get_error_code();
54
+ return array(
55
+ 'error' => true,
56
+ 'errcode' => $code,
57
+ 'message' => $user_id->get_error_message($code)
58
+ );
59
+ }
60
+
61
+ update_user_meta($user_id, '_wtlwp_user', true);
62
+ update_user_meta($user_id, '_wtlwp_created', Wp_Temporary_Login_Without_Password_Common::get_current_gmt_timestamp());
63
+ update_user_meta($user_id, '_wtlwp_expire', Wp_Temporary_Login_Without_Password_Common::get_user_expire_time($time));
64
+ update_user_meta($user_id, '_wtlwp_token', Wp_Temporary_Login_Without_Password_Common::generate_wtlwp_token($user_id));
65
+
66
+ update_user_meta($user_id, 'show_welcome_panel', 0);
67
+
68
+ return $user_id;
69
+ }
70
+
71
+ /**
72
+ * get the expiry duration
73
+ *
74
+ * @param type $key
75
+ * @return boolean|array
76
+ */
77
+ public static function get_expiry_duration($key = '') {
78
+
79
+ $expiry_duration = array(
80
+ '3_days' => array(
81
+ 'value' => DAY_IN_SECONDS * 3,
82
+ 'label' => __('Three Days', Wp_Temporary_Login_Without_Password_i18n::$text_domain)
83
+ ),
84
+ 'day' => array(
85
+ 'value' => DAY_IN_SECONDS,
86
+ 'label' => __('One Day', Wp_Temporary_Login_Without_Password_i18n::$text_domain)
87
+ ),
88
+ '3_hours' => array(
89
+ 'value' => HOUR_IN_SECONDS * 3,
90
+ 'label' => __('Three Hours', Wp_Temporary_Login_Without_Password_i18n::$text_domain)
91
+ ),
92
+ 'hour' => array(
93
+ 'value' => HOUR_IN_SECONDS,
94
+ 'label' => __('One Hour', Wp_Temporary_Login_Without_Password_i18n::$text_domain)
95
+ ),
96
+ 'week' => array(
97
+ 'value' => WEEK_IN_SECONDS,
98
+ 'label' => __('One Week', Wp_Temporary_Login_Without_Password_i18n::$text_domain)
99
+ ),
100
+ 'month' => array(
101
+ 'value' => DAY_IN_SECONDS * 30,
102
+ 'label' => __('One Month', Wp_Temporary_Login_Without_Password_i18n::$text_domain)
103
+ ),
104
+ );
105
+
106
+
107
+ if (empty($key)) {
108
+ return $expiry_duration;
109
+ } elseif (isset($expiry_duration[$key])) {
110
+ return $expiry_duration[$key];
111
+ } else {
112
+ return;
113
+ }
114
+ }
115
+
116
+ static function get_expiry_duration_html($selected = '') {
117
+
118
+ $p = '';
119
+ $r = '';
120
+
121
+ $expiry_duration = self::get_expiry_duration();
122
+
123
+ foreach ($expiry_duration as $key => $duration) {
124
+ $label = $duration['label'];
125
+ if ($selected == $key)
126
+ $p = "\n\t<option selected='selected' value='" . esc_attr($key) . "'>$label</option>";
127
+ else
128
+ $r .= "\n\t<option value='" . esc_attr($key) . "'>$label</option>";
129
+ }
130
+
131
+ echo $p . $r;
132
+ }
133
+
134
+ public static function generate_password() {
135
+ return wp_generate_password(absint(15), true, false);
136
+ }
137
+
138
+ public static function get_user_expire_time($time = '') {
139
+ $data = self::get_expiry_duration($time);
140
+ $range = !empty($data['value']) ? $data['value'] : DAY_IN_SECONDS;
141
+
142
+ return self::get_current_gmt_timestamp() + floatval($range);
143
+ }
144
+
145
+ public static function get_current_gmt_timestamp() {
146
+ return strtotime(gmdate('Y-m-d H:i:s', time()));
147
+ }
148
+
149
+ public static function get_temporary_logins() {
150
+
151
+ $args = array(
152
+ 'fields' => 'all',
153
+ 'meta_key' => '_wtlwp_expire',
154
+ 'order' => 'DESC',
155
+ 'orderby' => 'meta_value',
156
+ 'meta_query' => array(
157
+ 0 => array(
158
+ 'key' => '_wtlwp_user',
159
+ 'value' => 1
160
+ )
161
+ )
162
+ );
163
+
164
+ if (!empty($role)) {
165
+ $args['role'] = $role;
166
+ }
167
+
168
+ $users = new WP_User_Query($args);
169
+
170
+ if (!($users->results)) {
171
+ return false;
172
+ }
173
+
174
+ return $users->results;
175
+ }
176
+
177
+ public static function format_date_display($stamp = 0, $type = 'date_format') {
178
+
179
+ $type_format = 'date_format';
180
+ if ($type == 'date_format') {
181
+ $type_format = get_option('date_format');
182
+ } else if ($type == 'time_format') {
183
+ $type_format = get_option('time_format');
184
+ }
185
+
186
+
187
+ $timezone = get_option('timezone_string');
188
+
189
+ if (empty($timezone)) {
190
+ return date($type_format, $stamp);
191
+ }
192
+
193
+ $date = new DateTime('@' . $stamp);
194
+
195
+ $date->setTimezone(new DateTimeZone($timezone));
196
+
197
+ return $date->format($type_format);
198
+ }
199
+
200
+ public static function get_redirect_link($result = array()) {
201
+
202
+ if (empty($result)) {
203
+ return false;
204
+ }
205
+
206
+ $base_url = menu_page_url('wp-temporary-login-without-password', false);
207
+
208
+ if (empty($base_url)) {
209
+ return false;
210
+ }
211
+
212
+ $query_string = '';
213
+ if (!empty($result['status'])) {
214
+ if ($result['status'] == 'success') {
215
+ $query_string .= '&wtlwp_success=1';
216
+ } elseif ($result['status'] == 'error') {
217
+ $query_string .= '&wtlwp_error=1';
218
+ }
219
+ }
220
+
221
+ if (!empty($result['message'])) {
222
+ $query_string .= '&wtlwp_message=' . $result['message'];
223
+ }
224
+
225
+ $redirect_link = $base_url . $query_string;
226
+
227
+ return $redirect_link;
228
+ }
229
+
230
+ public static function can_manage_wtlwp($user_id = 0) {
231
+
232
+ if (empty($user_id)) {
233
+ $user_id = get_current_user_id();
234
+ }
235
+
236
+ if (empty($user_id)) {
237
+ return false;
238
+ }
239
+
240
+ $check = get_user_meta($user_id, '_wtlwp_user', true);
241
+
242
+ return !empty($check) ? false : true;
243
+ }
244
+
245
+ public static function is_login_expired($user_id = 0) {
246
+
247
+ if (empty($user_id)) {
248
+ $user_id = get_current_user_id();
249
+ }
250
+
251
+ if (empty($user_id)) {
252
+ return false;
253
+ }
254
+
255
+ $expire = get_user_meta($user_id, '_wtlwp_expire', true);
256
+
257
+ return !empty($expire) && self::get_current_gmt_timestamp() >= floatval($expire) ? true : false;
258
+ }
259
+
260
+ public static function generate_wtlwp_token($user_id) {
261
+ $str = $user_id . time() . uniqid('', true);
262
+ return md5($str);
263
+ }
264
+
265
+ public static function get_valid_user_based_on_wtlwp_token($token = '', $user_id = 0, $fields = 'all') {
266
+ $users_data = array();
267
+ if (empty($token)) {
268
+ return false;
269
+ }
270
+
271
+ $args = array(
272
+ 'fields' => $fields,
273
+ 'meta_key' => '_wtlwp_expire',
274
+ 'order' => 'DESC',
275
+ 'orderby' => 'meta_value',
276
+ 'meta_query' => array(
277
+ 0 => array(
278
+ 'key' => '_wtlwp_token',
279
+ 'value' => sanitize_text_field($token),
280
+ 'compare' => '='
281
+ )
282
+ )
283
+ );
284
+
285
+ $users = new WP_User_Query($args);
286
+
287
+ if (empty($users->results)) {
288
+ return false;
289
+ }
290
+
291
+ $users_data = $users->results;
292
+ foreach ($users_data as $key => $user) {
293
+ $expire = get_user_meta($user->ID, '_wtlwp_expire', true);
294
+ if ($expire <= self::get_current_gmt_timestamp()) {
295
+ unset($users_data[$key]);
296
+ }
297
+ }
298
+
299
+ return $users_data;
300
+ }
301
+
302
+ public static function is_valid_temporary_login($user_id = 0, $check_expiry = true) {
303
+
304
+ if (empty($user_id)) {
305
+ return false;
306
+ }
307
+
308
+ $check = get_user_meta($user_id, '_wtlwp_user', true);
309
+
310
+ if(!empty($check) && $check_expiry) {
311
+ $check = !(self::is_login_expired($user_id));
312
+ }
313
+
314
+ return !empty($check) ? true : false;
315
+ }
316
+
317
+ public static function get_manage_login_url($user_id, $action = '') {
318
+
319
+ if (empty($user_id) || empty($action)) {
320
+ return;
321
+ }
322
+
323
+ $base_url = menu_page_url('wp-temporary-login-without-password', false);
324
+ $args = array();
325
+
326
+ switch($action) {
327
+ case 'disable';
328
+ $args = array('wtlwp_action' => 'disable','user_id' => $user_id);
329
+ break;
330
+ case 'enable';
331
+ $args = array('wtlwp_action' => 'enable','user_id' => $user_id);
332
+ break;
333
+ case 'delete';
334
+ $args = array('wtlwp_action' => 'delete','user_id' => $user_id);
335
+ break;
336
+ default:
337
+ break;
338
+ }
339
+
340
+ $manage_login_url = '';
341
+ if (!empty($args)) {
342
+ $base_url = add_query_arg($args, trailingslashit($base_url));
343
+ $manage_login_url = wp_nonce_url($base_url, 'manage-temporary-login_' . $user_id, 'manage-temporary-login');
344
+ }
345
+
346
+ return $manage_login_url;
347
+ }
348
+
349
+ public static function get_login_url($user_id) {
350
+
351
+ if (empty($user_id) ) {
352
+ return;
353
+ }
354
+
355
+ $is_valid_temporary_login = self::is_valid_temporary_login($user_id, false);
356
+ if (!$is_valid_temporary_login) {
357
+ return;
358
+ }
359
+
360
+ $wtlwp_token = get_user_meta($user_id, '_wtlwp_token', true);
361
+ if (empty($wtlwp_token)) {
362
+ return;
363
+ }
364
+
365
+ $login_url = add_query_arg('wtlwp_token', $wtlwp_token, trailingslashit(admin_url()));
366
+
367
+ return $login_url;
368
+ }
369
+
370
+ public static function manage_login($user_id = 0, $action = '') {
371
+
372
+ if (empty($user_id) || empty($action)) {
373
+ return;
374
+ }
375
+
376
+ $is_valid_temporary_login = self::is_valid_temporary_login($user_id, false);
377
+ if (!$is_valid_temporary_login) {
378
+ return;
379
+ }
380
+
381
+ $manage_login = false;
382
+ if ($action == 'disable') {
383
+ $manage_login = update_user_meta($user_id, '_wtlwp_expire', self::get_current_gmt_timestamp());
384
+ } elseif ($action == 'enable') {
385
+ $manage_login = update_user_meta($user_id, '_wtlwp_expire', self::get_user_expire_time());
386
+ }
387
+
388
+ if ($manage_login) {
389
+ return true;
390
+ }
391
+
392
+ return false;
393
+ }
394
+
395
+ public static function time_elapsed_string($time, $ago = false) {
396
+
397
+ if ($ago) {
398
+ $etime = self::get_current_gmt_timestamp() - $time;
399
+ } else {
400
+ $etime = $time - self::get_current_gmt_timestamp();
401
+ }
402
+
403
+ if ($etime < 1) {
404
+ return __('Expired', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
405
+ }
406
+
407
+ $a = array(365 * 24 * 60 * 60 => 'year',
408
+ 30 * 24 * 60 * 60 => 'month',
409
+ 24 * 60 * 60 => 'day',
410
+ 60 * 60 => 'hour',
411
+ 60 => 'minute',
412
+ 1 => 'second'
413
+ );
414
+
415
+ $a_plural = array('year' => 'years',
416
+ 'month' => 'months',
417
+ 'day' => 'days',
418
+ 'hour' => 'hours',
419
+ 'minute' => 'minutes',
420
+ 'second' => 'seconds'
421
+ );
422
+
423
+ foreach ($a as $secs => $str) {
424
+ $d = $etime / $secs;
425
+ if ($d >= 1) {
426
+ $r = round($d);
427
+ if ($ago) {
428
+ return __(sprintf('%d %s ago', $r, ($r > 1 ? $a_plural[$str] : $str)), Wp_Temporary_Login_Without_Password_i18n::$text_domain);
429
+ } else {
430
+ return __(sprintf('%d %s remaining', $r, ($r > 1 ? $a_plural[$str] : $str)), Wp_Temporary_Login_Without_Password_i18n::$text_domain);
431
+ }
432
+ }
433
+ }
434
+ }
435
+
436
+ public static function get_blocked_pages() {
437
+ $blocked_pages = array('wp-temporary-login-without-password', 'user-new.php', 'user-edit.php', 'profile.php');
438
+ $blocked_pages = apply_filters('wtlwp_restricted_pages_for_temporary_users', $blocked_pages);
439
+ return $blocked_pages;
440
+ }
441
+
442
+ }
includes/class-wp-temporary-login-without-password-i18n.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Define the internationalization functionality
5
+ */
6
+ class Wp_Temporary_Login_Without_Password_i18n {
7
+
8
+ static $text_domain = 'wp-temporary-login-without-password';
9
+
10
+ public function load_plugin_textdomain() {
11
+
12
+ load_plugin_textdomain(
13
+ self::$text_domain, false, dirname(dirname(plugin_basename(__FILE__))) . '/languages/'
14
+ );
15
+ }
16
+
17
+ }
includes/class-wp-temporary-login-without-password-layout.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Wp_Temporary_Login_Without_Password_Layout {
4
+
5
+ public static function prepare_header_footer_row() {
6
+
7
+ $row = '';
8
+
9
+ $row .= '<th class="manage-column column-details" colspan="2">' . __('Users', Wp_Temporary_Login_Without_Password_i18n::$text_domain) . '</th>';
10
+ $row .= '<th class="manage-column column-email">' . __('Role', Wp_Temporary_Login_Without_Password_i18n::$text_domain) . '</th>';
11
+ $row .= '<th class="manage-column column-expired">' . __('Last Logged In', Wp_Temporary_Login_Without_Password_i18n::$text_domain) . '</th>';
12
+ $row .= '<th class="manage-column column-expired">' . __('Expiry', Wp_Temporary_Login_Without_Password_i18n::$text_domain) . '</th>';
13
+ $row .= '<th class="manage-column column-expired">' . __('Actions', Wp_Temporary_Login_Without_Password_i18n::$text_domain) . '</th>';
14
+
15
+ return $row;
16
+ }
17
+
18
+ public static function prepare_empty_user_row() {
19
+
20
+ $row = '';
21
+
22
+ $row .= '<tr class="tempadmin-single-user-row tempadmin-empty-users-row standard">';
23
+ $row .= '<td colspan="6">';
24
+ $row .= '<span class="description">' . __('You have not created any temporary logins yet.', Wp_Temporary_Login_Without_Password_i18n::$text_domain) . '</span>';
25
+ $row .= '</td>';
26
+ $row .= '</tr>';
27
+
28
+ return $row;
29
+ }
30
+
31
+ public static function prepare_single_user_row($user = OBJECT, $class = 'standard') {
32
+ global $wpdb;
33
+ if (is_numeric($user) && !is_object($user)) {
34
+ $user = get_user_by('id', $user);
35
+ }
36
+
37
+ $create = get_user_meta($user->ID, '_wtlwp_created', true);
38
+ $expire = get_user_meta($user->ID, '_wtlwp_expire', true);
39
+ $token = get_user_meta($user->ID, '_wtlwp_token', true);
40
+ $last_login_time = get_user_meta($user->ID, '_wtlwp_last_login', true);
41
+
42
+ $last_login_str = __('Not yet logged in', Wp_Temporary_Login_Without_Password_i18n::$text_domain);
43
+ if (!empty($last_login_time)) {
44
+ $last_login_str = Wp_Temporary_Login_Without_Password_Common::time_elapsed_string($last_login_time, true);
45
+ }
46
+
47
+ $wtlwp_status = "Active";
48
+ if (Wp_Temporary_Login_Without_Password_Common::is_login_expired($user->ID)) {
49
+ $wtlwp_status = "Expired";
50
+ }
51
+
52
+ $capabilities = $user->{$wpdb->prefix . 'capabilities'};
53
+ $wp_roles = new WP_Roles();
54
+ foreach ($wp_roles->role_names as $role => $name) {
55
+ if (array_key_exists($role, $capabilities)) {
56
+ $user_role = $name;
57
+ }
58
+ }
59
+
60
+
61
+ $user_details = "<div><span>";
62
+ if ((esc_attr($user->first_name))) {
63
+ $user_details .= "<span>" . esc_attr($user->first_name) . "</span>";
64
+ }
65
+
66
+ if ((esc_attr($user->last_name))) {
67
+ $user_details .= "<span> " . esc_attr($user->last_name) . "</span>";
68
+ }
69
+
70
+ $user_details .= " (<span class='wtlwp-user-login'>" . esc_attr($user->user_login) . ")</span><br />";
71
+
72
+ if ((esc_attr($user->user_email))) {
73
+ $user_details .= "<span><b>" . esc_attr($user->user_email) . "</b></span> <br />";
74
+ }
75
+
76
+ $user_details .= "</span></div>";
77
+
78
+ $row = '';
79
+
80
+ $row .= '<tr id="single-user-' . absint($user->ID) . '" class="tempadmin-single-user-row">';
81
+ $row .= '<td class="email column-details" colspan="2">' . $user_details . '</td>';
82
+ $row .= '<td class="wtlwp-token column-role">' . esc_attr($user_role) . '</td>';
83
+ $row .= '<td class="wtlwp-token column-last-login">' . esc_attr($last_login_str) . '</td>';
84
+
85
+ $row .= '<td class="expired column-expired wtlwp-status-' . strtolower($wtlwp_status) . '">';
86
+ if (!empty($expire)) {
87
+ $row .= Wp_Temporary_Login_Without_Password_Common::time_elapsed_string($expire);
88
+ }
89
+ $row .= '</td>';
90
+ $row .= '<td class="wtlwp-token column-email">' . self::prepare_row_actions($user, $wtlwp_status) . '</td>';
91
+ $row .= '</tr>';
92
+
93
+ return $row;
94
+ }
95
+
96
+ public static function prepare_row_actions($user, $wtlwp_status) {
97
+
98
+ $action_row = '<div class="actions">';
99
+
100
+ $user_id = $user->ID;
101
+
102
+ $delete_login_url = Wp_Temporary_Login_Without_Password_Common::get_manage_login_url($user_id, 'delete');
103
+ $disable_login_url = Wp_Temporary_Login_Without_Password_Common::get_manage_login_url($user_id, 'disable');
104
+ $enable_login_url = Wp_Temporary_Login_Without_Password_Common::get_manage_login_url($user_id, 'enable');
105
+
106
+ if (strtolower($wtlwp_status) == 'expired') {
107
+ $action_row .= '<span class="enable"><a title="'. __('Reactivate for one day', Wp_Temporary_Login_Without_Password_i18n::$text_domain) .'" href="' . $enable_login_url . '"><span class="dashicons dashicons-lock"></a></span></span>';
108
+ } elseif (strtolower($wtlwp_status) == 'active') {
109
+ $action_row .= '<span class="disable"><a title="'. __('Disable', Wp_Temporary_Login_Without_Password_i18n::$text_domain) .'" href="' . $disable_login_url . '"><span class="dashicons dashicons-unlock"></span></a></span>';
110
+ }
111
+
112
+ $action_row .= '<span class="edit"><a title="'. __('Delete', Wp_Temporary_Login_Without_Password_i18n::$text_domain) .'" href="' . $delete_login_url . '"><span class="dashicons dashicons-no"></span></a></span>';
113
+ $action_row .= '<span class="edit"><span id="text-' . $user->ID . '" class="dashicons dashicons-admin-links wtlwp-copy-to-clipboard" title="'. __('Copy login link', Wp_Temporary_Login_Without_Password_i18n::$text_domain) .'" data-clipboard-text="' . Wp_Temporary_Login_Without_Password_Common::get_login_url($user->ID) . '"></span></span>';
114
+ $action_row .= '<span id="copied-text-' . $user->ID . '" class="copied-text-message"></span>';
115
+ $action_row .= '</div>';
116
+
117
+ return $action_row;
118
+ }
119
+
120
+ }
includes/class-wp-temporary-login-without-password-loader.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Register all actions and filters for the plugin
5
+ */
6
+ class Wp_Temporary_Login_Without_Password_Loader {
7
+
8
+ protected $actions;
9
+ protected $filters;
10
+
11
+ public function __construct() {
12
+ $this->actions = array();
13
+ $this->filters = array();
14
+ }
15
+
16
+ public function add_action($hook, $component, $callback, $priority = 10, $accepted_args = 1) {
17
+ $this->actions = $this->add($this->actions, $hook, $component, $callback, $priority, $accepted_args);
18
+ }
19
+
20
+ public function add_filter($hook, $component, $callback, $priority = 10, $accepted_args = 1) {
21
+ $this->filters = $this->add($this->filters, $hook, $component, $callback, $priority, $accepted_args);
22
+ }
23
+
24
+ private function add($hooks, $hook, $component, $callback, $priority, $accepted_args) {
25
+
26
+ $hooks[] = array(
27
+ 'hook' => $hook,
28
+ 'component' => $component,
29
+ 'callback' => $callback,
30
+ 'priority' => $priority,
31
+ 'accepted_args' => $accepted_args
32
+ );
33
+
34
+ return $hooks;
35
+ }
36
+
37
+ public function run() {
38
+
39
+ foreach ($this->filters as $hook) {
40
+ add_filter($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']);
41
+ }
42
+
43
+ foreach ($this->actions as $hook) {
44
+ add_action($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']);
45
+ }
46
+ }
47
+
48
+ }
includes/class-wp-temporary-login-without-password.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Wp_Temporary_Login_Without_Password {
4
+
5
+ protected $loader;
6
+
7
+ protected $plugin_name;
8
+
9
+ protected $version;
10
+
11
+ public function __construct() {
12
+
13
+ $this->plugin_name = 'wp-temporary-login-without-password';
14
+ $this->version = '1.0';
15
+
16
+ $this->load_dependencies();
17
+ $this->set_locale();
18
+ $this->define_admin_hooks();
19
+ $this->define_public_hooks();
20
+ }
21
+
22
+ public function define_constant($name, $value) {
23
+ if (!defined($name)) {
24
+ define($name, $value);
25
+ }
26
+ }
27
+
28
+ private function load_dependencies() {
29
+
30
+ require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-wp-temporary-login-without-password-loader.php';
31
+ require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-wp-temporary-login-without-password-i18n.php';
32
+ require_once plugin_dir_path(dirname(__FILE__)) . 'admin/class-wp-temporary-login-without-password-admin.php';
33
+ require_once plugin_dir_path(dirname(__FILE__)) . 'public/class-wp-temporary-login-without-password-public.php';
34
+
35
+ require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-wp-temporary-login-without-password-common.php';
36
+ require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-wp-temporary-login-without-password-layout.php';
37
+
38
+ $this->loader = new Wp_Temporary_Login_Without_Password_Loader();
39
+ }
40
+
41
+ private function set_locale() {
42
+
43
+ $plugin_i18n = new Wp_Temporary_Login_Without_Password_i18n();
44
+
45
+ $this->loader->add_action('plugins_loaded', $plugin_i18n, 'load_plugin_textdomain');
46
+ }
47
+
48
+ private function define_admin_hooks() {
49
+
50
+ $plugin_admin = new Wp_Temporary_Login_Without_Password_Admin($this->get_plugin_name(), $this->get_version());
51
+
52
+ $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_styles');
53
+ $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts');
54
+
55
+ $this->loader->add_action('admin_menu', $plugin_admin, 'admin_menu');
56
+ $this->loader->add_action('admin_init', $plugin_admin, 'create_user');
57
+ $this->loader->add_action('admin_init', $plugin_admin, 'delete_user');
58
+ $this->loader->add_action('admin_init', $plugin_admin, 'manage_temporary_login');
59
+ $this->loader->add_action('admin_notices', $plugin_admin, 'display_admin_notices');
60
+
61
+ $this->loader->add_filter('wpmu_welcome_notification', $plugin_admin, 'disable_welcome_notification', 10, 5);
62
+ }
63
+
64
+ private function define_public_hooks() {
65
+
66
+ $plugin_public = new Wp_Temporary_Login_Without_Password_Public($this->get_plugin_name(), $this->get_version());
67
+
68
+ $this->loader->add_action('init', $plugin_public, 'init_wtlwp');
69
+ $this->loader->add_filter('authenticate', $plugin_public, 'wtlwp_authenticate', 10, 3);
70
+ }
71
+
72
+ public function run() {
73
+ $this->loader->run();
74
+ }
75
+
76
+ public function get_plugin_name() {
77
+ return $this->plugin_name;
78
+ }
79
+
80
+ public function get_loader() {
81
+ return $this->loader;
82
+ }
83
+
84
+ public function get_version() {
85
+ return $this->version;
86
+ }
87
+
88
+ }
includes/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden
index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden
languages/wp-temporary-login-without-password.pot ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Loco Gettext template
2
+ #, fuzzy
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: WP Temporary Login Without Password\n"
6
+ "Report-Msgid-Bugs-To: \n"
7
+ "POT-Creation-Date: Tue Jul 26 2016 14:37:55 GMT+0530 (IST)\n"
8
+ "POT-Revision-Date: Wed Aug 03 2016 14:53:20 GMT+0530 (IST)\n"
9
+ "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
10
+ "Last-Translator: \n"
11
+ "Language-Team: \n"
12
+ "Language: \n"
13
+ "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION\n"
14
+ "MIME-Version: 1.0\n"
15
+ "Content-Type: text/plain; charset=UTF-8\n"
16
+ "Content-Transfer-Encoding: 8bit\n"
17
+ "X-Poedit-SourceCharset: UTF-8\n"
18
+ "X-Poedit-Basepath: .\n"
19
+ "X-Poedit-SearchPath-0: ..\n"
20
+ "X-Poedit-KeywordsList: _:1;gettext:1;dgettext:2;ngettext:1,2;dngettext:2,3;"
21
+ "__:1;_e:1;_c:1;_n:1,2;_n_noop:1,2;_nc:1,2;__ngettext:1,2;__ngettext_noop:1,2;"
22
+ "_x:1,2c;_ex:1,2c;_nx:1,2,4c;_nx_noop:1,2,3c;_n_js:1,2;_nx_js:1,2,3c;"
23
+ "esc_attr__:1;esc_html__:1;esc_attr_e:1;esc_html_e:1;esc_attr_x:1,2c;"
24
+ "esc_html_x:1,2c;comments_number_link:2,3;t:1;st:1;trans:1;transChoice:1,2\n"
25
+ "X-Generator: Loco - https://localise.biz/"
26
+
27
+ #. Name of the plugin
28
+ msgid "Temporary Login Without Password"
29
+ msgstr ""
30
+
31
+ #. URI of the plugin
32
+ msgid "http://storeapps.org"
33
+ msgstr ""
34
+
35
+ #. Description of the plugin
36
+ msgid ""
37
+ "Create a temporary login link for your developer with any role using which "
38
+ "they can access to your sytem without login and password for limited period "
39
+ "of time."
40
+ msgstr ""
41
+
42
+ #. Author of the plugin
43
+ msgid "StoreApps"
44
+ msgstr ""
45
+
46
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:26 ../admin/class-
47
+ #: wp-temporary-login-without-password-admin.php:26 ../templates/admin_settings.
48
+ #: php:3
49
+ msgid "Temporary Logins"
50
+ msgstr ""
51
+
52
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:181
53
+ msgid "User creation failed"
54
+ msgstr ""
55
+
56
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:185
57
+ msgid "You do not have permission to create a temporary login"
58
+ msgstr ""
59
+
60
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:189
61
+ msgid "Email already is in use"
62
+ msgstr ""
63
+
64
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:193
65
+ msgid "Please enter valid email address. Email field should not be empty"
66
+ msgstr ""
67
+
68
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:197
69
+ msgid "Please enter valid email address"
70
+ msgstr ""
71
+
72
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:201
73
+ msgid "User you are trying to delete is not temporary"
74
+ msgstr ""
75
+
76
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:205
77
+ msgid "Nonce failed"
78
+ msgstr ""
79
+
80
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:209
81
+ msgid "Invalid action"
82
+ msgstr ""
83
+
84
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:214
85
+ msgid "Unknown error occured"
86
+ msgstr ""
87
+
88
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:222
89
+ msgid "Login created successfully!"
90
+ msgstr ""
91
+
92
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:226
93
+ msgid "Login deleted successfully!"
94
+ msgstr ""
95
+
96
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:230
97
+ msgid "Login disabled successfully!"
98
+ msgstr ""
99
+
100
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:234
101
+ msgid "Login enabled successfully!"
102
+ msgstr ""
103
+
104
+ #: ../admin/class-wp-temporary-login-without-password-admin.php:238
105
+ msgid "Success!"
106
+ msgstr ""
107
+
108
+ #: ../includes/class-wp-temporary-login-without-password-common.php:82
109
+ msgid "Three Days"
110
+ msgstr ""
111
+
112
+ #: ../includes/class-wp-temporary-login-without-password-common.php:86
113
+ msgid "One Day"
114
+ msgstr ""
115
+
116
+ #: ../includes/class-wp-temporary-login-without-password-common.php:90
117
+ msgid "Three Hours"
118
+ msgstr ""
119
+
120
+ #: ../includes/class-wp-temporary-login-without-password-common.php:94
121
+ msgid "One Hour"
122
+ msgstr ""
123
+
124
+ #: ../includes/class-wp-temporary-login-without-password-common.php:98
125
+ msgid "One Week"
126
+ msgstr ""
127
+
128
+ #: ../includes/class-wp-temporary-login-without-password-common.php:102
129
+ msgid "One Month"
130
+ msgstr ""
131
+
132
+ #: ../includes/class-wp-temporary-login-without-password-common.php:404
133
+ msgid "Expired"
134
+ msgstr ""
135
+
136
+ #: ../includes/class-wp-temporary-login-without-password-layout.php:9
137
+ msgid "Users"
138
+ msgstr ""
139
+
140
+ #: ../includes/class-wp-temporary-login-without-password-layout.php:10 ..
141
+ #: /templates/new_login.php:19
142
+ msgid "Role"
143
+ msgstr ""
144
+
145
+ #: ../includes/class-wp-temporary-login-without-password-layout.php:11
146
+ msgid "Last Logged In"
147
+ msgstr ""
148
+
149
+ #: ../includes/class-wp-temporary-login-without-password-layout.php:12 ..
150
+ #: /templates/new_login.php:27
151
+ msgid "Expiry"
152
+ msgstr ""
153
+
154
+ #: ../includes/class-wp-temporary-login-without-password-layout.php:13
155
+ msgid "Actions"
156
+ msgstr ""
157
+
158
+ #: ../includes/class-wp-temporary-login-without-password-layout.php:24
159
+ msgid "You have not created any temporary logins yet."
160
+ msgstr ""
161
+
162
+ #: ../includes/class-wp-temporary-login-without-password-layout.php:42
163
+ msgid "Not yet logged in"
164
+ msgstr ""
165
+
166
+ #: ../includes/class-wp-temporary-login-without-password-layout.php:107
167
+ msgid "Reactivate for one day"
168
+ msgstr ""
169
+
170
+ #: ../includes/class-wp-temporary-login-without-password-layout.php:109
171
+ msgid "Disable"
172
+ msgstr ""
173
+
174
+ #: ../includes/class-wp-temporary-login-without-password-layout.php:112
175
+ msgid "Delete"
176
+ msgstr ""
177
+
178
+ #: ../includes/class-wp-temporary-login-without-password-layout.php:113
179
+ msgid "Copy login link"
180
+ msgstr ""
181
+
182
+ #: ../public/class-wp-temporary-login-without-password-public.php:16
183
+ msgid "Token empty"
184
+ msgstr ""
185
+
186
+ #: ../public/class-wp-temporary-login-without-password-public.php:17
187
+ msgid "Authentication failed"
188
+ msgstr ""
189
+
190
+ #: ../public/class-wp-temporary-login-without-password-public.php:63
191
+ msgid "You don't have permission to access this page"
192
+ msgstr ""
193
+
194
+ #: ../public/class-wp-temporary-login-without-password-public.php:75
195
+ msgid "ERROR: Invalid username."
196
+ msgstr ""
197
+
198
+ #: ../public/class-wp-temporary-login-without-password-public.php:84
199
+ msgid "ERROR: User can't find."
200
+ msgstr ""
201
+
202
+ #: ../templates/admin_settings.php:3
203
+ msgid "Create New"
204
+ msgstr ""
205
+
206
+ #: ../templates/admin_settings.php:13
207
+ msgid "Here's a temporary login link"
208
+ msgstr ""
209
+
210
+ #: ../templates/admin_settings.php:15
211
+ msgid "Click To Copy"
212
+ msgstr ""
213
+
214
+ #: ../templates/admin_settings.php:17
215
+ msgid ""
216
+ "User can directly login to wordpress admin panel without username and "
217
+ "password by opening this link."
218
+ msgstr ""
219
+
220
+ #: ../templates/new_login.php:1
221
+ msgid "Create a new Temporary Login"
222
+ msgstr ""
223
+
224
+ #: ../templates/new_login.php:5
225
+ msgid "Email*"
226
+ msgstr ""
227
+
228
+ #: ../templates/new_login.php:10
229
+ msgid "First Name"
230
+ msgstr ""
231
+
232
+ #: ../templates/new_login.php:15
233
+ msgid "Last Name"
234
+ msgstr ""
235
+
236
+ #: ../templates/new_login.php:36
237
+ msgid "Submit"
238
+ msgstr ""
239
+
240
+ #: ../templates/new_login.php:36
241
+ msgid "or"
242
+ msgstr ""
243
+
244
+ #: ../templates/new_login.php:36
245
+ msgid "Cancel"
246
+ msgstr ""
license.txt ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ Preamble
10
+
11
+ The licenses for most software are designed to take away your
12
+ freedom to share and change it. By contrast, the GNU General Public
13
+ License is intended to guarantee your freedom to share and change free
14
+ software--to make sure the software is free for all its users. This
15
+ General Public License applies to most of the Free Software
16
+ Foundation's software and to any other program whose authors commit to
17
+ using it. (Some other Free Software Foundation software is covered by
18
+ the GNU Lesser General Public License instead.) You can apply it to
19
+ your programs, too.
20
+
21
+ When we speak of free software, we are referring to freedom, not
22
+ price. Our General Public Licenses are designed to make sure that you
23
+ have the freedom to distribute copies of free software (and charge for
24
+ this service if you wish), that you receive source code or can get it
25
+ if you want it, that you can change the software or use pieces of it
26
+ in new free programs; and that you know you can do these things.
27
+
28
+ To protect your rights, we need to make restrictions that forbid
29
+ anyone to deny you these rights or to ask you to surrender the rights.
30
+ These restrictions translate to certain responsibilities for you if you
31
+ distribute copies of the software, or if you modify it.
32
+
33
+ For example, if you distribute copies of such a program, whether
34
+ gratis or for a fee, you must give the recipients all the rights that
35
+ you have. You must make sure that they, too, receive or can get the
36
+ source code. And you must show them these terms so they know their
37
+ rights.
38
+
39
+ We protect your rights with two steps: (1) copyright the software, and
40
+ (2) offer you this license which gives you legal permission to copy,
41
+ distribute and/or modify the software.
42
+
43
+ Also, for each author's protection and ours, we want to make certain
44
+ that everyone understands that there is no warranty for this free
45
+ software. If the software is modified by someone else and passed on, we
46
+ want its recipients to know that what they have is not the original, so
47
+ that any problems introduced by others will not reflect on the original
48
+ authors' reputations.
49
+
50
+ Finally, any free program is threatened constantly by software
51
+ patents. We wish to avoid the danger that redistributors of a free
52
+ program will individually obtain patent licenses, in effect making the
53
+ program proprietary. To prevent this, we have made it clear that any
54
+ patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+ The precise terms and conditions for copying, distribution and
57
+ modification follow.
58
+
59
+ GNU GENERAL PUBLIC LICENSE
60
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+ 0. This License applies to any program or other work which contains
63
+ a notice placed by the copyright holder saying it may be distributed
64
+ under the terms of this General Public License. The "Program", below,
65
+ refers to any such program or work, and a "work based on the Program"
66
+ means either the Program or any derivative work under copyright law:
67
+ that is to say, a work containing the Program or a portion of it,
68
+ either verbatim or with modifications and/or translated into another
69
+ language. (Hereinafter, translation is included without limitation in
70
+ the term "modification".) Each licensee is addressed as "you".
71
+
72
+ Activities other than copying, distribution and modification are not
73
+ covered by this License; they are outside its scope. The act of
74
+ running the Program is not restricted, and the output from the Program
75
+ is covered only if its contents constitute a work based on the
76
+ Program (independent of having been made by running the Program).
77
+ Whether that is true depends on what the Program does.
78
+
79
+ 1. You may copy and distribute verbatim copies of the Program's
80
+ source code as you receive it, in any medium, provided that you
81
+ conspicuously and appropriately publish on each copy an appropriate
82
+ copyright notice and disclaimer of warranty; keep intact all the
83
+ notices that refer to this License and to the absence of any warranty;
84
+ and give any other recipients of the Program a copy of this License
85
+ along with the Program.
86
+
87
+ You may charge a fee for the physical act of transferring a copy, and
88
+ you may at your option offer warranty protection in exchange for a fee.
89
+
90
+ 2. You may modify your copy or copies of the Program or any portion
91
+ of it, thus forming a work based on the Program, and copy and
92
+ distribute such modifications or work under the terms of Section 1
93
+ above, provided that you also meet all of these conditions:
94
+
95
+ a) You must cause the modified files to carry prominent notices
96
+ stating that you changed the files and the date of any change.
97
+
98
+ b) You must cause any work that you distribute or publish, that in
99
+ whole or in part contains or is derived from the Program or any
100
+ part thereof, to be licensed as a whole at no charge to all third
101
+ parties under the terms of this License.
102
+
103
+ c) If the modified program normally reads commands interactively
104
+ when run, you must cause it, when started running for such
105
+ interactive use in the most ordinary way, to print or display an
106
+ announcement including an appropriate copyright notice and a
107
+ notice that there is no warranty (or else, saying that you provide
108
+ a warranty) and that users may redistribute the program under
109
+ these conditions, and telling the user how to view a copy of this
110
+ License. (Exception: if the Program itself is interactive but
111
+ does not normally print such an announcement, your work based on
112
+ the Program is not required to print an announcement.)
113
+
114
+ These requirements apply to the modified work as a whole. If
115
+ identifiable sections of that work are not derived from the Program,
116
+ and can be reasonably considered independent and separate works in
117
+ themselves, then this License, and its terms, do not apply to those
118
+ sections when you distribute them as separate works. But when you
119
+ distribute the same sections as part of a whole which is a work based
120
+ on the Program, the distribution of the whole must be on the terms of
121
+ this License, whose permissions for other licensees extend to the
122
+ entire whole, and thus to each and every part regardless of who wrote it.
123
+
124
+ Thus, it is not the intent of this section to claim rights or contest
125
+ your rights to work written entirely by you; rather, the intent is to
126
+ exercise the right to control the distribution of derivative or
127
+ collective works based on the Program.
128
+
129
+ In addition, mere aggregation of another work not based on the Program
130
+ with the Program (or with a work based on the Program) on a volume of
131
+ a storage or distribution medium does not bring the other work under
132
+ the scope of this License.
133
+
134
+ 3. You may copy and distribute the Program (or a work based on it,
135
+ under Section 2) in object code or executable form under the terms of
136
+ Sections 1 and 2 above provided that you also do one of the following:
137
+
138
+ a) Accompany it with the complete corresponding machine-readable
139
+ source code, which must be distributed under the terms of Sections
140
+ 1 and 2 above on a medium customarily used for software interchange; or,
141
+
142
+ b) Accompany it with a written offer, valid for at least three
143
+ years, to give any third party, for a charge no more than your
144
+ cost of physically performing source distribution, a complete
145
+ machine-readable copy of the corresponding source code, to be
146
+ distributed under the terms of Sections 1 and 2 above on a medium
147
+ customarily used for software interchange; or,
148
+
149
+ c) Accompany it with the information you received as to the offer
150
+ to distribute corresponding source code. (This alternative is
151
+ allowed only for noncommercial distribution and only if you
152
+ received the program in object code or executable form with such
153
+ an offer, in accord with Subsection b above.)
154
+
155
+ The source code for a work means the preferred form of the work for
156
+ making modifications to it. For an executable work, complete source
157
+ code means all the source code for all modules it contains, plus any
158
+ associated interface definition files, plus the scripts used to
159
+ control compilation and installation of the executable. However, as a
160
+ special exception, the source code distributed need not include
161
+ anything that is normally distributed (in either source or binary
162
+ form) with the major components (compiler, kernel, and so on) of the
163
+ operating system on which the executable runs, unless that component
164
+ itself accompanies the executable.
165
+
166
+ If distribution of executable or object code is made by offering
167
+ access to copy from a designated place, then offering equivalent
168
+ access to copy the source code from the same place counts as
169
+ distribution of the source code, even though third parties are not
170
+ compelled to copy the source along with the object code.
171
+
172
+ 4. You may not copy, modify, sublicense, or distribute the Program
173
+ except as expressly provided under this License. Any attempt
174
+ otherwise to copy, modify, sublicense or distribute the Program is
175
+ void, and will automatically terminate your rights under this License.
176
+ However, parties who have received copies, or rights, from you under
177
+ this License will not have their licenses terminated so long as such
178
+ parties remain in full compliance.
179
+
180
+ 5. You are not required to accept this License, since you have not
181
+ signed it. However, nothing else grants you permission to modify or
182
+ distribute the Program or its derivative works. These actions are
183
+ prohibited by law if you do not accept this License. Therefore, by
184
+ modifying or distributing the Program (or any work based on the
185
+ Program), you indicate your acceptance of this License to do so, and
186
+ all its terms and conditions for copying, distributing or modifying
187
+ the Program or works based on it.
188
+
189
+ 6. Each time you redistribute the Program (or any work based on the
190
+ Program), the recipient automatically receives a license from the
191
+ original licensor to copy, distribute or modify the Program subject to
192
+ these terms and conditions. You may not impose any further
193
+ restrictions on the recipients' exercise of the rights granted herein.
194
+ You are not responsible for enforcing compliance by third parties to
195
+ this License.
196
+
197
+ 7. If, as a consequence of a court judgment or allegation of patent
198
+ infringement or for any other reason (not limited to patent issues),
199
+ conditions are imposed on you (whether by court order, agreement or
200
+ otherwise) that contradict the conditions of this License, they do not
201
+ excuse you from the conditions of this License. If you cannot
202
+ distribute so as to satisfy simultaneously your obligations under this
203
+ License and any other pertinent obligations, then as a consequence you
204
+ may not distribute the Program at all. For example, if a patent
205
+ license would not permit royalty-free redistribution of the Program by
206
+ all those who receive copies directly or indirectly through you, then
207
+ the only way you could satisfy both it and this License would be to
208
+ refrain entirely from distribution of the Program.
209
+
210
+ If any portion of this section is held invalid or unenforceable under
211
+ any particular circumstance, the balance of the section is intended to
212
+ apply and the section as a whole is intended to apply in other
213
+ circumstances.
214
+
215
+ It is not the purpose of this section to induce you to infringe any
216
+ patents or other property right claims or to contest validity of any
217
+ such claims; this section has the sole purpose of protecting the
218
+ integrity of the free software distribution system, which is
219
+ implemented by public license practices. Many people have made
220
+ generous contributions to the wide range of software distributed
221
+ through that system in reliance on consistent application of that
222
+ system; it is up to the author/donor to decide if he or she is willing
223
+ to distribute software through any other system and a licensee cannot
224
+ impose that choice.
225
+
226
+ This section is intended to make thoroughly clear what is believed to
227
+ be a consequence of the rest of this License.
228
+
229
+ 8. If the distribution and/or use of the Program is restricted in
230
+ certain countries either by patents or by copyrighted interfaces, the
231
+ original copyright holder who places the Program under this License
232
+ may add an explicit geographical distribution limitation excluding
233
+ those countries, so that distribution is permitted only in or among
234
+ countries not thus excluded. In such case, this License incorporates
235
+ the limitation as if written in the body of this License.
236
+
237
+ 9. The Free Software Foundation may publish revised and/or new versions
238
+ of the General Public License from time to time. Such new versions will
239
+ be similar in spirit to the present version, but may differ in detail to
240
+ address new problems or concerns.
241
+
242
+ Each version is given a distinguishing version number. If the Program
243
+ specifies a version number of this License which applies to it and "any
244
+ later version", you have the option of following the terms and conditions
245
+ either of that version or of any later version published by the Free
246
+ Software Foundation. If the Program does not specify a version number of
247
+ this License, you may choose any version ever published by the Free Software
248
+ Foundation.
249
+
250
+ 10. If you wish to incorporate parts of the Program into other free
251
+ programs whose distribution conditions are different, write to the author
252
+ to ask for permission. For software which is copyrighted by the Free
253
+ Software Foundation, write to the Free Software Foundation; we sometimes
254
+ make exceptions for this. Our decision will be guided by the two goals
255
+ of preserving the free status of all derivatives of our free software and
256
+ of promoting the sharing and reuse of software generally.
257
+
258
+ NO WARRANTY
259
+
260
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
+ REPAIR OR CORRECTION.
269
+
270
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
+ POSSIBILITY OF SUCH DAMAGES.
279
+
280
+ END OF TERMS AND CONDITIONS
281
+
282
+ How to Apply These Terms to Your New Programs
283
+
284
+ If you develop a new program, and you want it to be of the greatest
285
+ possible use to the public, the best way to achieve this is to make it
286
+ free software which everyone can redistribute and change under these terms.
287
+
288
+ To do so, attach the following notices to the program. It is safest
289
+ to attach them to the start of each source file to most effectively
290
+ convey the exclusion of warranty; and each file should have at least
291
+ the "copyright" line and a pointer to where the full notice is found.
292
+
293
+ <one line to give the program's name and a brief idea of what it does.>
294
+ Copyright (C) <year> <name of author>
295
+
296
+ This program is free software; you can redistribute it and/or modify
297
+ it under the terms of the GNU General Public License as published by
298
+ the Free Software Foundation; either version 2 of the License, or
299
+ (at your option) any later version.
300
+
301
+ This program is distributed in the hope that it will be useful,
302
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304
+ GNU General Public License for more details.
305
+
306
+ You should have received a copy of the GNU General Public License along
307
+ with this program; if not, write to the Free Software Foundation, Inc.,
308
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
+
310
+ Also add information on how to contact you by electronic and paper mail.
311
+
312
+ If the program is interactive, make it output a short notice like this
313
+ when it starts in an interactive mode:
314
+
315
+ Gnomovision version 69, Copyright (C) year name of author
316
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317
+ This is free software, and you are welcome to redistribute it
318
+ under certain conditions; type `show c' for details.
319
+
320
+ The hypothetical commands `show w' and `show c' should show the appropriate
321
+ parts of the General Public License. Of course, the commands you use may
322
+ be called something other than `show w' and `show c'; they could even be
323
+ mouse-clicks or menu items--whatever suits your program.
324
+
325
+ You should also get your employer (if you work as a programmer) or your
326
+ school, if any, to sign a "copyright disclaimer" for the program, if
327
+ necessary. Here is a sample; alter the names:
328
+
329
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
+
332
+ <signature of Ty Coon>, 1 April 1989
333
+ Ty Coon, President of Vice
334
+
335
+ This General Public License does not permit incorporating your program into
336
+ proprietary programs. If your program is a subroutine library, you may
337
+ consider it more useful to permit linking proprietary applications with the
338
+ library. If this is what you want to do, use the GNU Lesser General
339
+ Public License instead of this License.
public/class-wp-temporary-login-without-password-public.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Wp_Temporary_Login_Without_Password_Public {
4
+
5
+ private $plugin_name;
6
+ private $version;
7
+
8
+ public function __construct($plugin_name, $version) {
9
+ $this->plugin_name = $plugin_name;
10
+ $this->version = $version;
11
+ }
12
+
13
+ public static function get_error_messages($error_code) {
14
+
15
+ $error_messages = array(
16
+ 'token' => __('Token empty', Wp_Temporary_Login_Without_Password_i18n::$text_domain),
17
+ 'unauth' => __('Authentication failed', Wp_Temporary_Login_Without_Password_i18n::$text_domain)
18
+ );
19
+
20
+ if (!empty($error_code)) {
21
+ return (isset($error_messages[$error_code]) ? $error_messages[$error_code] : '');
22
+ }
23
+
24
+ return $error_messages;
25
+ }
26
+
27
+ public function init_wtlwp() {
28
+
29
+ if (!is_user_logged_in() && !empty($_GET['wtlwp_token'])) {
30
+
31
+ $error_messages = array();
32
+
33
+ $wtlwp_token = $_GET['wtlwp_token'];
34
+ $users = Wp_Temporary_Login_Without_Password_Common::get_valid_user_based_on_wtlwp_token($wtlwp_token);
35
+
36
+ if (empty($users)) {
37
+ wp_safe_redirect(home_url());
38
+ } else {
39
+ $user = $users[0];
40
+
41
+ $user_id = $user->ID;
42
+ $user_login = $user->login;
43
+ update_user_meta($user_id, '_wtlwp_last_login', Wp_Temporary_Login_Without_Password_Common::get_current_gmt_timestamp());
44
+ wp_set_current_user($user_id, $user_login);
45
+ wp_set_auth_cookie($user_id);
46
+
47
+ do_action('wp_login', $user_login, $user);
48
+ }
49
+ }
50
+
51
+ if (is_user_logged_in()) {
52
+ $user_id = get_current_user_id();
53
+ if (!empty($user_id) && Wp_Temporary_Login_Without_Password_Common::is_valid_temporary_login($user_id, false)) {
54
+ if (Wp_Temporary_Login_Without_Password_Common::is_login_expired($user_id)) {
55
+ wp_logout();
56
+ wp_safe_redirect(home_url());
57
+ exit();
58
+ } else {
59
+ global $pagenow;
60
+ $bloked_pages = Wp_Temporary_Login_Without_Password_Common::get_blocked_pages();
61
+ $page = !empty($_GET['page']) ? $_GET['page'] : '';
62
+ if ((!empty($page) && in_array($page, $bloked_pages)) || (!empty($pagenow) && in_array($pagenow, $bloked_pages))) {
63
+ wp_die(__("You don't have permission to access this page", Wp_Temporary_Login_Without_Password_i18n::$text_domain));
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+
70
+ function wtlwp_authenticate($user, $username, $password) {
71
+
72
+ $user_id = username_exists($username);
73
+
74
+ if (!$user_id) {
75
+ return new WP_Error('denied', __("ERROR: Invalid username."));
76
+ }
77
+
78
+ $check_expiry = false;
79
+ $is_valid_temporary_login = Wp_Temporary_Login_Without_Password_Common::is_valid_temporary_login($user_id, $check_expiry);
80
+ if ($is_valid_temporary_login) {
81
+ $is_login_expired = Wp_Temporary_Login_Without_Password_Common::is_login_expired($user_id);
82
+ update_user_meta($user_id, '_wtlwp_last_login', Wp_Temporary_Login_Without_Password_Common::get_current_gmt_timestamp());
83
+ if ($is_login_expired) {
84
+ $user = new WP_Error('denied', __("ERROR: User can't find."));
85
+ remove_action('authenticate', 'wp_authenticate_username_password', 20);
86
+ }
87
+ }
88
+
89
+ return $user;
90
+ }
91
+
92
+ }
public/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden
readme.txt ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Temporary Login Without Password ===
2
+ Contributors: storeapps, niravmehta, malayladu
3
+ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CPTHCDC382KVA
4
+ Tags: admin, custom login, login, temporary login, wp admin, wordpress admin, access, expiration, user, login without password
5
+ Requires at least: 3.0.1
6
+ Tested up to: 4.5.3
7
+ Stable tag: 1.0
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ Create self-expiring, temporary admin accounts. Easily share direct login links (no need for username / password) with your developers or editors.
12
+
13
+ == Description ==
14
+
15
+ Create self-expiring, automatic login links for WordPress. Give them to developers when they ask for admin access to your site. Or an editor for a quick review of work done. Login works just by opening the link, no password needed.
16
+
17
+ Using "Temporary Login Without Password" plugin you can create a self expiring account for someone and give them a special link with which they can login to your WordPress without needing a username and password.
18
+
19
+ You can choose when the login expires, as well as the role of the temporary account.
20
+
21
+ Really useful when you need to give admin access to a developer for support or for performing routine tasks.
22
+
23
+ Use this plugin along with [WP Security Audit Log](https://wordpress.org/plugins/wp-security-audit-log/) plugin to track what the person does after loggin in.
24
+
25
+
26
+ **Spread The Word**
27
+
28
+ If you like Temporary Login Without Password, please leave a five star review on WordPress and also spread the word about it. That helps fellow website owners assess Temporary Login Without Password easily and benefit from it!
29
+
30
+ == Installation ==
31
+
32
+ 1. Unzip downloaded folder and upload it to 'wp-content/plugins/' folder
33
+ 2. Activate the plugin through the 'Plugins' menu in WordPress
34
+ 3. Go to Users > Temporary Login section and create a new temporary login.
35
+
36
+ == Screenshots ==
37
+
38
+ 1. Create a new temporary login.
39
+ 2. List of all (Active/Expired) temporary logins.
40
+
41
+ == Changelog ==
42
+
43
+ = 1.0 =
44
+
45
+ - Initial Release
screenshots/screenshot-1.png ADDED
Binary file
screenshots/screenshot-2.png ADDED
Binary file
templates/admin_settings.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php ?>
2
+ <div class="wrap wtlwp-settings-wrap">
3
+ <h2> <?php echo __('Temporary Logins', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?> <span class="page-title-action" id="add-new-wtlwp-form-button"><?php _e('Create New', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?></span> </h2>
4
+ <div class="wtlwp-settings">
5
+ <!-- Add New Form Start -->
6
+ <div class="wrap new-wtlwp-form" id="new-wtlwp-form">
7
+ <?php load_template(WTLWP_PLUGIN_DIR . '/templates/new_login.php'); ?>
8
+ </div>
9
+
10
+ <?php if(!empty($wtlwp_generated_url)) { ?>
11
+
12
+ <div class="wrap generated-wtlwp-login-link" id="generated-wtlwp-login-link">
13
+ <p><?php _e("Here's a temporary login link", Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?></p>
14
+ <input id="wtlwp-click-to-copy-btn" type="text" class="wtlwp-wide-input" value="<?php echo $wtlwp_generated_url; ?>">
15
+ <button class="wtlwp-click-to-copy-btn" data-clipboard-action="copy" data-clipboard-target="#wtlwp-click-to-copy-btn"><?php echo __('Click To Copy', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?></button>
16
+ <span id="copied-text-message-wtlwp-click-to-copy-btn"></span>
17
+ <p><?php _e("User can directly login to wordpress admin panel without username and password by opening this link.", Wp_Temporary_Login_Without_Password_i18n::$text_domain);
18
+ if(!empty($user_email)) {
19
+ echo __(sprintf(" <a href='mailto:%s'>Email</a> copied login link to user.", $user_email ), Wp_Temporary_Login_Without_Password_i18n::$text_domain);
20
+ }
21
+ ?>
22
+ </p>
23
+
24
+ </div>
25
+ <?php } ?>
26
+ <!-- Add New Form End -->
27
+
28
+ <!-- List All Generated Logins Start -->
29
+ <div class="wrap list-wtlwp-logins" id="list-wtlwp-logins">
30
+ <?php load_template(WTLWP_PLUGIN_DIR . '/templates/list_temporary_logins.php'); ?>
31
+ </div>
32
+ <!-- List All Generated Logins End -->
33
+ </div>
34
+ </div>
templates/list_temporary_logins.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <table class="wp-list-table widefat fixed striped users">
2
+ <thead>
3
+ <?php echo Wp_Temporary_Login_Without_Password_Layout::prepare_header_footer_row(); ?>
4
+ </thead>
5
+
6
+ <tbody>
7
+ <?php
8
+ $users = Wp_Temporary_Login_Without_Password_Common::get_temporary_logins();
9
+
10
+ if (is_array($users) && count($users) > 0) {
11
+
12
+ foreach ($users as $user) {
13
+ echo Wp_Temporary_Login_Without_Password_Layout::prepare_single_user_row($user);
14
+ }
15
+ } else {
16
+ echo Wp_Temporary_Login_Without_Password_Layout::prepare_empty_user_row();
17
+ }
18
+
19
+ ?>
20
+
21
+ </tbody>
22
+
23
+ <tfoot>
24
+ <?php echo Wp_Temporary_Login_Without_Password_Layout::prepare_header_footer_row(); ?>
25
+ </tfoot>
26
+ </table>
templates/new_login.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <h2> <?php echo __('Create a new Temporary Login', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?></h2>
2
+ <form method="post">
3
+ <table class="form-table wtlwp-form">
4
+ <tr class="form-field form-required">
5
+ <th scope="row" class="wtlwp-form-row"> <label for="user_email"><?php echo __('Email*', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?> </label></th>
6
+ <td><input name="wtlwp_data[user_email]" type="text" id="user_email" value="" aria-required="true" autocapitalize="none" autocorrect="off" maxlength="60" class="wtlwp-form-input"/></td>
7
+ </tr>
8
+
9
+ <tr class="form-field form-required">
10
+ <th scope="row" class="wtlwp-form-row"> <label for="user_first_name"><?php echo __('First Name', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?> </label></th>
11
+ <td><input name="wtlwp_data[user_first_name]" type="text" id="user_first_name" value="" aria-required="true" autocapitalize="none" autocorrect="off" maxlength="60" class="wtlwp-form-input"/></td>
12
+ </tr>
13
+
14
+ <tr class="form-field form-required">
15
+ <th scope="row" class="wtlwp-form-row"> <label for="user_last_name"><?php echo __('Last Name', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?> </label></th>
16
+ <td><input name="wtlwp_data[user_last_name]" type="text" id="user_last_name" value="" aria-required="true" autocapitalize="none" autocorrect="off" maxlength="60" class="wtlwp-form-input"/></td>
17
+ </tr>
18
+ <tr class="form-field">
19
+ <th scope="row" class="wtlwp-form-row"><label for="adduser-role"><?php echo __('Role', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?></label></th>
20
+ <td><select name="wtlwp_data[role]" id="user-role">
21
+ <?php wp_dropdown_roles('administrator'); ?>
22
+ </select>
23
+ </td>
24
+ </tr>
25
+
26
+ <tr class="form-field">
27
+ <th scope="row" class="wtlwp-form-row"><label for="adduser-role"><?php echo __('Expiry', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?></label></th>
28
+ <td><select name="wtlwp_data[expiry]" id="user-expiry-time">
29
+ <?php Wp_Temporary_Login_Without_Password_Common::get_expiry_duration_html(); ?>
30
+ </select>
31
+ </td>
32
+ </tr>
33
+
34
+ <tr class="form-field">
35
+ <th scope="row" class="wtlwp-form-row"><label for="adduser-role"></label></th>
36
+ <td><p class="submit"><input type="submit" class="button button-primary wtlwp-form-submit-button" value="<?php _e('Submit', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?>" class="button button-primary" id="generatetemporarylogin" name="generate_temporary_login"> <?php _e('or', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?> <span class="cancel-new-login-form" id="cancel-new-login-form"><?php _e('Cancel', Wp_Temporary_Login_Without_Password_i18n::$text_domain); ?></span></p>
37
+ </td>
38
+ </tr>
39
+ <?php wp_nonce_field('wtlwp_generate_login_url', 'wtlwp-nonce', true, true); ?>
40
+ </table>
41
+ </form>
temporary-login-without-password.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Plugin Name: Temporary Login Without Password
5
+ * Plugin URI: http://storeapps.org
6
+ * Description: Create a temporary login link with any role using which one can access to your sytem without username and password for limited period of time.
7
+ * Version: 1.0
8
+ * Author: StoreApps
9
+ * Author URI: http://storeapps.org
10
+ * License: GPL-2.0+
11
+ * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
12
+ * Text Domain: wp-temporary-login-without-password
13
+ * Domain Path: /languages
14
+ */
15
+ // If this file is called directly, abort.
16
+ if (!defined('WPINC')) {
17
+ die;
18
+ }
19
+
20
+ // Include main class file
21
+ require plugin_dir_path(__FILE__) . 'includes/class-wp-temporary-login-without-password.php';
22
+
23
+ function run_wp_temporary_login_without_password() {
24
+ $plugin = new Wp_Temporary_Login_Without_Password();
25
+ $plugin->define_constant('WTLWP_PLUGIN_DIR', dirname(__FILE__));
26
+ $plugin->run();
27
+ }
28
+
29
+ run_wp_temporary_login_without_password();
uninstall.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Fired when the plugin is uninstalled.
5
+ *
6
+ * When populating this file, consider the following flow
7
+ * of control:
8
+ *
9
+ * - This method should be static
10
+ * - Check if the $_REQUEST content actually is the plugin name
11
+ * - Run an admin referrer check to make sure it goes through authentication
12
+ * - Verify the output of $_GET makes sense
13
+ * - Repeat with other user roles. Best directly by using the links/query string parameters.
14
+ * - Repeat things for multisite. Once for a single site in the network, once sitewide.
15
+ *
16
+ * This file may be updated more in future version of the Boilerplate; however, this is the
17
+ * general skeleton and outline for how the file should work.
18
+ *
19
+ * For more information, see the following discussion:
20
+ * https://github.com/tommcfarlin/WordPress-Plugin-Boilerplate/pull/123#issuecomment-28541913
21
+ *
22
+ * @link http://storeapps.org
23
+ * @since 1.0
24
+ *
25
+ * @package Wp_Temporary_Login_Without_Password
26
+ */
27
+
28
+ // If uninstall not called from WordPress, then exit.
29
+ if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
30
+ exit;
31
+ }