Version Description
October 31, 2016 =
New: Stream Alerts is here! Get notified when something happens in your WP-Admin, so that you don't miss a thing. (#844)
Tweak: Better support for the latest version of Yoast SEO (#838)
Tweak: Better support for the latest version of WooCommerce (#851#864)
Tweak: Better taxonomy labelling (#859)
Fix: Fatal error caused by conflict with Yoast SEO (#879)
Fix: Activating Stream through WP CLI now works (#880)
Fix: Custom roles track properly (#836)
Props @chacha, @lukecarbis, @johnbillion, @rheinardkorf, @frozzare, @johnregan3, @jacobschweitzer, @wrongware
Download this release
Release Info
Developer | lukecarbis |
Plugin | Stream |
Version | 3.1 |
Comparing to | |
See all releases |
Code changes from version 3.0.7 to 3.1
- alerts/class-alert-trigger-action.php +176 -0
- alerts/class-alert-trigger-author.php +155 -0
- alerts/class-alert-trigger-context.php +188 -0
- alerts/class-alert-type-die.php +44 -0
- alerts/class-alert-type-email.php +181 -0
- alerts/class-alert-type-highlight.php +301 -0
- alerts/class-alert-type-ifttt.php +307 -0
- alerts/class-alert-type-menu-alert.php +173 -0
- alerts/class-alert-type-none.php +41 -0
- alerts/js/alert-type-highlight.js +77 -0
- classes/class-admin.php +14 -1
- classes/class-alert-trigger.php +95 -0
- classes/class-alert-type.php +78 -0
- classes/class-alert.php +337 -0
- classes/class-alerts-list.php +374 -0
- classes/class-alerts.php +777 -0
- classes/class-connectors.php +7 -7
- classes/class-form-generator.php +13 -11
- classes/class-install.php +6 -6
- classes/class-list-table.php +17 -5
- classes/class-live-update.php +1 -1
- classes/class-network.php +4 -2
- classes/class-plugin.php +18 -5
- classes/class-preview-list-table.php +62 -0
- classes/class-settings.php +3 -3
- connectors/class-connector-buddypress.php +2 -2
- connectors/class-connector-gravityforms.php +1 -1
- connectors/class-connector-user-switching.php +1 -1
- connectors/class-connector-woocommerce.php +16 -8
- connectors/class-connector-wordpress-seo.php +32 -7
- exporters/class-exporter-csv.php +1 -1
- includes/db-updates.php +17 -0
- readme.txt +14 -2
- stream.php +1 -1
- ui/css/admin.css +45 -29
- ui/css/alerts-list.css +142 -0
- ui/js/alerts-list.js +11 -0
- ui/js/alerts.js +272 -0
- ui/js/live-updates.js +2 -1
- ui/js/settings.js +8 -4
alerts/class-alert-trigger-action.php
ADDED
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Trigger on an Action.
|
4 |
+
*
|
5 |
+
* @package WP_Stream
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace WP_Stream;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Alert_Trigger_Action
|
12 |
+
*
|
13 |
+
* @package WP_Stream
|
14 |
+
*/
|
15 |
+
class Alert_Trigger_Action extends Alert_Trigger {
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Unique identifier
|
19 |
+
*
|
20 |
+
* @var string
|
21 |
+
*/
|
22 |
+
public $slug = 'action';
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Meta key used in forms.
|
26 |
+
*
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
public $meta_key = 'trigger_action';
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Field key used in database
|
33 |
+
*
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
public $field_key = 'wp_stream_trigger_action';
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Checks if a record matches the criteria from the trigger.
|
40 |
+
*
|
41 |
+
* @see Alert_Trigger::check_record().
|
42 |
+
* @param bool $success Status of previous checks.
|
43 |
+
* @param int $record_id Record ID.
|
44 |
+
* @param array $recordarr Record data.
|
45 |
+
* @param Alert $alert The Alert being worked on.
|
46 |
+
* @return bool False on failure, otherwise should return original value of $success.
|
47 |
+
*/
|
48 |
+
public function check_record( $success, $record_id, $recordarr, $alert ) {
|
49 |
+
if ( ! empty( $alert->alert_meta['trigger_action'] ) && $recordarr['action'] !== $alert->alert_meta['trigger_action'] ) {
|
50 |
+
return false;
|
51 |
+
}
|
52 |
+
return $success;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Adds fields to the trigger form.
|
57 |
+
*
|
58 |
+
* @see Alert_Trigger::add_fields().
|
59 |
+
* @param Form_Generator $form The Form Object to add to.
|
60 |
+
* @param Alert $alert The Alert being worked on.
|
61 |
+
* @return void
|
62 |
+
*/
|
63 |
+
public function add_fields( $form, $alert = array() ) {
|
64 |
+
$value = '';
|
65 |
+
if ( is_object( $alert ) && ! empty( $alert->alert_meta['trigger_action'] ) ) {
|
66 |
+
$value = $alert->alert_meta['trigger_action'];
|
67 |
+
}
|
68 |
+
|
69 |
+
$args = array(
|
70 |
+
'name' => esc_attr( $this->field_key ),
|
71 |
+
'value' => esc_attr( $value ),
|
72 |
+
'options' => $this->get_values(),
|
73 |
+
'classes' => 'wp_stream_ajax_forward',
|
74 |
+
'data' => array(
|
75 |
+
'placeholder' => __( 'Any Action', 'stream' ),
|
76 |
+
),
|
77 |
+
);
|
78 |
+
$form->add_field( 'select2', $args );
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Validate and save Alert object
|
83 |
+
*
|
84 |
+
* @see Alert_Trigger::save_fields().
|
85 |
+
* @param Alert $alert The Alert being worked on.
|
86 |
+
* @return void
|
87 |
+
*/
|
88 |
+
public function save_fields( $alert ) {
|
89 |
+
$input = wp_stream_filter_input( INPUT_POST, $this->field_key );
|
90 |
+
if ( array_key_exists( $input, $this->get_values( true ) ) ) {
|
91 |
+
$alert->alert_meta['trigger_action'] = $input;
|
92 |
+
} else {
|
93 |
+
$alert->alert_meta['trigger_action'] = '';
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Generate array of possible action values
|
99 |
+
*
|
100 |
+
* @param bool $flat If the array should be multidimensional.
|
101 |
+
* @return array
|
102 |
+
*/
|
103 |
+
public function get_values( $flat = false ) {
|
104 |
+
$action_values = array();
|
105 |
+
foreach ( $this->get_terms_labels( 'action' ) as $action_id => $action_data ) {
|
106 |
+
if ( ! $flat ) {
|
107 |
+
$action_values[] = array( 'id' => $action_id, 'text' => $action_data );
|
108 |
+
} else {
|
109 |
+
$action_values[ $action_id ] = $action_data;
|
110 |
+
}
|
111 |
+
}
|
112 |
+
return $action_values;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Function will return all terms labels of given column
|
117 |
+
*
|
118 |
+
* @todo refactor Settings::get_terms_labels into general utility
|
119 |
+
* @param string $column string Name of the column.
|
120 |
+
* @return array
|
121 |
+
*/
|
122 |
+
public function get_terms_labels( $column ) {
|
123 |
+
$return_labels = array();
|
124 |
+
|
125 |
+
if ( isset( $this->plugin->connectors->term_labels[ 'stream_' . $column ] ) ) {
|
126 |
+
if ( 'context' === $column && isset( $this->plugin->connectors->term_labels['stream_connector'] ) ) {
|
127 |
+
$connectors = $this->plugin->connectors->term_labels['stream_connector'];
|
128 |
+
$contexts = $this->plugin->connectors->term_labels['stream_context'];
|
129 |
+
|
130 |
+
foreach ( $connectors as $connector => $connector_label ) {
|
131 |
+
$return_labels[ $connector ]['label'] = $connector_label;
|
132 |
+
foreach ( $contexts as $context => $context_label ) {
|
133 |
+
if ( isset( $this->plugin->connectors->contexts[ $connector ] ) && array_key_exists( $context, $this->plugin->connectors->contexts[ $connector ] ) ) {
|
134 |
+
$return_labels[ $connector ]['children'][ $context ] = $context_label;
|
135 |
+
}
|
136 |
+
}
|
137 |
+
}
|
138 |
+
} else {
|
139 |
+
$return_labels = $this->plugin->connectors->term_labels[ 'stream_' . $column ];
|
140 |
+
}
|
141 |
+
|
142 |
+
ksort( $return_labels );
|
143 |
+
}
|
144 |
+
return $return_labels;
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Returns the trigger's value for the given alert.
|
149 |
+
*
|
150 |
+
* @see Alert_Trigger::get_display_value().
|
151 |
+
* @param string $context The location this data will be displayed in.
|
152 |
+
* @param Alert $alert Alert being processed.
|
153 |
+
* @return string
|
154 |
+
*/
|
155 |
+
function get_display_value( $context = 'normal', $alert ) {
|
156 |
+
$action = ( ! empty( $alert->alert_meta['trigger_action'] ) ) ? $alert->alert_meta['trigger_action'] : null;
|
157 |
+
|
158 |
+
if ( 'post_title' === $context ) {
|
159 |
+
if ( empty( $action ) ) {
|
160 |
+
$action = __( 'performed any action on', 'stream' );
|
161 |
+
}
|
162 |
+
} else {
|
163 |
+
if ( empty( $action ) ) {
|
164 |
+
$action = __( 'Any Action', 'stream' );
|
165 |
+
} else {
|
166 |
+
$actions = $this->plugin->connectors->term_labels['stream_action'];
|
167 |
+
if ( ! empty( $actions[ $action ] ) ) {
|
168 |
+
$action = $actions[ $action ];
|
169 |
+
}
|
170 |
+
$action = ucfirst( $action );
|
171 |
+
}
|
172 |
+
}
|
173 |
+
|
174 |
+
return ucfirst( $action );
|
175 |
+
}
|
176 |
+
}
|
alerts/class-alert-trigger-author.php
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Trigger for an Author.
|
4 |
+
*
|
5 |
+
* @package WP_Stream
|
6 |
+
*/
|
7 |
+
namespace WP_Stream;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class Alert_Trigger_Author
|
11 |
+
*
|
12 |
+
* @package WP_Stream
|
13 |
+
*/
|
14 |
+
class Alert_Trigger_Author extends Alert_Trigger {
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Unique identifier
|
18 |
+
*
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
public $slug = 'author';
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Field key used in database
|
25 |
+
*
|
26 |
+
* @var string
|
27 |
+
*/
|
28 |
+
public $field_key = 'wp_stream_trigger_author';
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Checks if a record matches the criteria from the trigger.
|
32 |
+
*
|
33 |
+
* @see Alert_Trigger::check_record().
|
34 |
+
* @param bool $success Status of previous checks.
|
35 |
+
* @param int $record_id Record ID.
|
36 |
+
* @param array $recordarr Record data.
|
37 |
+
* @param Alert $alert The Alert being worked on.
|
38 |
+
* @return bool False on failure, otherwise should return original value of $success.
|
39 |
+
*/
|
40 |
+
public function check_record( $success, $record_id, $recordarr, $alert ) {
|
41 |
+
if ( ! empty( $alert->alert_meta['trigger_author'] ) && intval( $alert->alert_meta['trigger_author'] ) !== intval( $recordarr['user_id'] ) ) {
|
42 |
+
return false;
|
43 |
+
}
|
44 |
+
return $success;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Adds fields to the trigger form.
|
49 |
+
*
|
50 |
+
* @see Alert_Trigger::add_fields().
|
51 |
+
* @param Form_Generator $form The Form Object to add to.
|
52 |
+
* @param Alert $alert The Alert being worked on.
|
53 |
+
* @return void
|
54 |
+
*/
|
55 |
+
public function add_fields( $form, $alert = array() ) {
|
56 |
+
$value = '';
|
57 |
+
if ( is_object( $alert ) && ! empty( $alert->alert_meta['trigger_author'] ) ) {
|
58 |
+
$value = $alert->alert_meta['trigger_author'];
|
59 |
+
}
|
60 |
+
|
61 |
+
$args = array(
|
62 |
+
'name' => esc_attr( $this->field_key ),
|
63 |
+
'value' => esc_attr( $value ),
|
64 |
+
'options' => $this->get_values(),
|
65 |
+
'classes' => 'wp_stream_ajax_forward',
|
66 |
+
'data' => array(
|
67 |
+
'placeholder' => __( 'Any Author', 'stream' ),
|
68 |
+
),
|
69 |
+
);
|
70 |
+
$form->add_field( 'select2', $args );
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Generate array of possible action values
|
75 |
+
*
|
76 |
+
* @return array
|
77 |
+
*/
|
78 |
+
public function get_values() {
|
79 |
+
$all_records = array();
|
80 |
+
|
81 |
+
$user_count = count_users();
|
82 |
+
$total_users = $user_count['total_users'];
|
83 |
+
|
84 |
+
if ( $total_users > $this->plugin->admin->preload_users_max ) {
|
85 |
+
return array();
|
86 |
+
}
|
87 |
+
|
88 |
+
$users = array_map(
|
89 |
+
function( $user_id ) {
|
90 |
+
return new Author( $user_id );
|
91 |
+
},
|
92 |
+
get_users( array( 'fields' => 'ID' ) )
|
93 |
+
);
|
94 |
+
|
95 |
+
if ( is_multisite() && is_super_admin() ) {
|
96 |
+
$super_admins = array_map(
|
97 |
+
function( $login ) {
|
98 |
+
$user = get_user_by( 'login', $login );
|
99 |
+
return new Author( $user->ID );
|
100 |
+
},
|
101 |
+
get_super_admins()
|
102 |
+
);
|
103 |
+
$users = array_unique( array_merge( $users, $super_admins ) );
|
104 |
+
}
|
105 |
+
|
106 |
+
$users[] = new Author( 0, array( 'is_wp_cli' => true ) );
|
107 |
+
|
108 |
+
foreach ( $users as $user ) {
|
109 |
+
$all_records[] = array(
|
110 |
+
'id' => $user->id,
|
111 |
+
'text' => $user->get_display_name(),
|
112 |
+
);
|
113 |
+
}
|
114 |
+
return $all_records;
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Validate and save Alert object
|
119 |
+
*
|
120 |
+
* @see Alert_Trigger::save_fields().
|
121 |
+
* @param Alert $alert The Alert being worked on.
|
122 |
+
* @return void
|
123 |
+
*/
|
124 |
+
public function save_fields( $alert ) {
|
125 |
+
$input = wp_stream_filter_input( INPUT_POST, $this->field_key );
|
126 |
+
if ( array_key_exists( $input, $this->get_values( $alert ) ) ) {
|
127 |
+
$alert->alert_meta['trigger_author'] = $input;
|
128 |
+
} else {
|
129 |
+
$alert->alert_meta['trigger_author'] = '';
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Returns the trigger's value for the given alert.
|
135 |
+
*
|
136 |
+
* @see Alert_Trigger::get_display_value().
|
137 |
+
* @param string $context The location this data will be displayed in.
|
138 |
+
* @param Alert $alert Alert being processed.
|
139 |
+
* @return string
|
140 |
+
*/
|
141 |
+
function get_display_value( $context = 'normal', $alert ) {
|
142 |
+
$author = ( ! empty( $alert->alert_meta['trigger_author'] ) ) ? $alert->alert_meta['trigger_author'] : null;
|
143 |
+
if ( empty( $author ) ) {
|
144 |
+
$author = __( 'Any User', 'stream' );
|
145 |
+
} elseif ( is_numeric( $author ) ) {
|
146 |
+
$author_data = get_userdata( $author );
|
147 |
+
if ( $author_data ) {
|
148 |
+
$author = $author_data->display_name;
|
149 |
+
} else {
|
150 |
+
$author = __( 'Unknown User', 'stream' );
|
151 |
+
}
|
152 |
+
}
|
153 |
+
return ucfirst( $author );
|
154 |
+
}
|
155 |
+
}
|
alerts/class-alert-trigger-context.php
ADDED
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Trigger on Context.
|
4 |
+
*
|
5 |
+
* @package WP_Stream
|
6 |
+
*/
|
7 |
+
namespace WP_Stream;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class Alert_Trigger_Context
|
11 |
+
*
|
12 |
+
* @package WP_Stream
|
13 |
+
*/
|
14 |
+
class Alert_Trigger_Context extends Alert_Trigger {
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Unique identifier
|
18 |
+
*
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
public $slug = 'context';
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Field key used in database
|
25 |
+
*
|
26 |
+
* @var string
|
27 |
+
*/
|
28 |
+
public $field_key = 'wp_stream_trigger_context';
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Checks if a record matches the criteria from the trigger.
|
32 |
+
*
|
33 |
+
* @see Alert_Trigger::check_record().
|
34 |
+
* @param bool $success Status of previous checks.
|
35 |
+
* @param int $record_id Record ID.
|
36 |
+
* @param array $recordarr Record data.
|
37 |
+
* @param Alert $alert The Alert being worked on.
|
38 |
+
* @return bool False on failure, otherwise should return original value of $success.
|
39 |
+
*/
|
40 |
+
public function check_record( $success, $record_id, $recordarr, $alert ) {
|
41 |
+
if ( ! empty( $alert->alert_meta['trigger_connector'] ) && $recordarr['connector'] !== $alert->alert_meta['trigger_connector'] ) {
|
42 |
+
return false;
|
43 |
+
}
|
44 |
+
if ( ! empty( $alert->alert_meta['trigger_context'] ) && $recordarr['context'] !== $alert->alert_meta['trigger_context'] ) {
|
45 |
+
return false;
|
46 |
+
}
|
47 |
+
return $success;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Adds fields to the trigger form.
|
52 |
+
*
|
53 |
+
* @see Alert_Trigger::add_fields().
|
54 |
+
* @param Form_Generator $form The Form Object to add to.
|
55 |
+
* @param Alert $alert The Alert being worked on.
|
56 |
+
* @return void
|
57 |
+
*/
|
58 |
+
public function add_fields( $form, $alert = array() ) {
|
59 |
+
$connector = '';
|
60 |
+
if ( is_object( $alert ) && ! empty( $alert->alert_meta['trigger_connector'] ) ) {
|
61 |
+
$connector = $alert->alert_meta['trigger_connector'];
|
62 |
+
}
|
63 |
+
|
64 |
+
$context = '';
|
65 |
+
if ( is_object( $alert ) && ! empty( $alert->alert_meta['trigger_context'] ) ) {
|
66 |
+
$context = $alert->alert_meta['trigger_context'];
|
67 |
+
}
|
68 |
+
|
69 |
+
// Context dropdown menu.
|
70 |
+
$context_values = array();
|
71 |
+
|
72 |
+
$form->add_field( 'select2', array(
|
73 |
+
'name' => 'wp_stream_trigger_connector_or_context',
|
74 |
+
'options' => $this->get_values(),
|
75 |
+
'classes' => 'wp_stream_ajax_forward connector_or_context',
|
76 |
+
'data' => array(
|
77 |
+
'placeholder' => __( 'Any Context', 'stream' ),
|
78 |
+
),
|
79 |
+
) );
|
80 |
+
|
81 |
+
$form->add_field( 'hidden', array(
|
82 |
+
'name' => 'wp_stream_trigger_connector',
|
83 |
+
'value' => $connector,
|
84 |
+
'classes' => 'connector wp_stream_ajax_forward',
|
85 |
+
) );
|
86 |
+
|
87 |
+
$form->add_field( 'hidden', array(
|
88 |
+
'name' => 'wp_stream_trigger_context',
|
89 |
+
'value' => $context,
|
90 |
+
'classes' => 'context wp_stream_ajax_forward',
|
91 |
+
) );
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Validate and save Alert object
|
96 |
+
*
|
97 |
+
* @see Alert_Trigger::save_fields().
|
98 |
+
* @param Alert $alert The Alert being worked on.
|
99 |
+
* @return void
|
100 |
+
*/
|
101 |
+
public function save_fields( $alert ) {
|
102 |
+
$alert->alert_meta['trigger_connector'] = wp_stream_filter_input( INPUT_POST, 'wp_stream_trigger_connector' );
|
103 |
+
$alert->alert_meta['trigger_context'] = wp_stream_filter_input( INPUT_POST, 'wp_stream_trigger_context' );
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Generate array of possible action values
|
108 |
+
*
|
109 |
+
* @return array
|
110 |
+
*/
|
111 |
+
public function get_values() {
|
112 |
+
foreach ( $this->get_terms_labels( 'context' ) as $context_id => $context_data ) {
|
113 |
+
if ( is_array( $context_data ) ) {
|
114 |
+
$child_values = array();
|
115 |
+
if ( isset( $context_data['children'] ) ) {
|
116 |
+
$child_values = array();
|
117 |
+
foreach ( $context_data['children'] as $child_id => $child_value ) {
|
118 |
+
$child_values[] = array( 'id' => $context_id . '-' . $child_id, 'text' => $child_value, 'parent' => $context_id );
|
119 |
+
}
|
120 |
+
}
|
121 |
+
if ( isset( $context_data['label'] ) ) {
|
122 |
+
$context_values[] = array( 'id' => $context_id, 'text' => $context_data['label'], 'children' => $child_values );
|
123 |
+
}
|
124 |
+
} else {
|
125 |
+
$context_values[] = array( 'id' => $context_id, 'text' => $context_data );
|
126 |
+
}
|
127 |
+
}
|
128 |
+
return $context_values;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Function will return all terms labels of given column
|
133 |
+
*
|
134 |
+
* @todo refactor Settings::get_terms_labels into general utility
|
135 |
+
* @param string $column string Name of the column.
|
136 |
+
* @return array
|
137 |
+
*/
|
138 |
+
public function get_terms_labels( $column ) {
|
139 |
+
$return_labels = array();
|
140 |
+
|
141 |
+
if ( isset( $this->plugin->connectors->term_labels[ 'stream_' . $column ] ) ) {
|
142 |
+
if ( 'context' === $column && isset( $this->plugin->connectors->term_labels['stream_connector'] ) ) {
|
143 |
+
$connectors = $this->plugin->connectors->term_labels['stream_connector'];
|
144 |
+
$contexts = $this->plugin->connectors->term_labels['stream_context'];
|
145 |
+
|
146 |
+
foreach ( $connectors as $connector => $connector_label ) {
|
147 |
+
$return_labels[ $connector ]['label'] = $connector_label;
|
148 |
+
foreach ( $contexts as $context => $context_label ) {
|
149 |
+
if ( isset( $this->plugin->connectors->contexts[ $connector ] ) && array_key_exists( $context, $this->plugin->connectors->contexts[ $connector ] ) ) {
|
150 |
+
$return_labels[ $connector ]['children'][ $context ] = $context_label;
|
151 |
+
}
|
152 |
+
}
|
153 |
+
}
|
154 |
+
} else {
|
155 |
+
$return_labels = $this->plugin->connectors->term_labels[ 'stream_' . $column ];
|
156 |
+
}
|
157 |
+
|
158 |
+
ksort( $return_labels );
|
159 |
+
}
|
160 |
+
return $return_labels;
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Returns the trigger's value for the given alert.
|
165 |
+
*
|
166 |
+
* @see Alert_Trigger::get_display_value().
|
167 |
+
* @param string $context The location this data will be displayed in.
|
168 |
+
* @param Alert $alert Alert being processed.
|
169 |
+
* @return string
|
170 |
+
*/
|
171 |
+
function get_display_value( $context = 'normal', $alert ) {
|
172 |
+
$context = ( ! empty( $alert->alert_meta['trigger_context'] ) ) ? $alert->alert_meta['trigger_context'] : null;
|
173 |
+
$connector = ( ! empty( $alert->alert_meta['trigger_connector'] ) ) ? $alert->alert_meta['trigger_connector'] : null;
|
174 |
+
if ( empty( $context ) && empty( $connector ) ) {
|
175 |
+
$context = __( 'Any Context', 'stream' );
|
176 |
+
} else {
|
177 |
+
$term_labels = $this->get_terms_labels( 'context' );
|
178 |
+
if ( ! empty( $term_labels[ $connector ]['children'][ $context ] ) ) {
|
179 |
+
$context = $term_labels[ $connector ]['children'][ $context ];
|
180 |
+
} else {
|
181 |
+
if ( ! empty( $term_labels[ $connector ]['label'] ) ) {
|
182 |
+
$context = $term_labels[ $connector ]['label'];
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}
|
186 |
+
return ucfirst( $context );
|
187 |
+
}
|
188 |
+
}
|
alerts/class-alert-type-die.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Used for debugging.
|
4 |
+
*
|
5 |
+
* @package WP_Stream
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace WP_Stream;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Alert_Type_Die
|
12 |
+
*
|
13 |
+
* @package WP_Stream
|
14 |
+
*/
|
15 |
+
class Alert_Type_Die extends Alert_Type {
|
16 |
+
/**
|
17 |
+
* Alert type name
|
18 |
+
*
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
public $name = 'Die Notifier';
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Alert type slug
|
25 |
+
*
|
26 |
+
* @var string
|
27 |
+
*/
|
28 |
+
public $slug = 'die';
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Triggers a script exit when an alert is triggered. Debugging use only.
|
32 |
+
*
|
33 |
+
* @param int $record_id Record that triggered notification.
|
34 |
+
* @param array $recordarr Record details.
|
35 |
+
* @param array $options Alert options.
|
36 |
+
* @return void
|
37 |
+
*/
|
38 |
+
public function alert( $record_id, $recordarr, $options ) {
|
39 |
+
echo '<pre>';
|
40 |
+
print_r( $recordarr ); // @codingStandardsIgnoreLine debug not loaded in production
|
41 |
+
echo '</pre>';
|
42 |
+
die( 'You have been notified!' );
|
43 |
+
}
|
44 |
+
}
|
alerts/class-alert-type-email.php
ADDED
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Email Alerts.
|
4 |
+
*
|
5 |
+
* Idea for future expansion: allow customization of email.
|
6 |
+
*
|
7 |
+
* @package WP_Stream
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace WP_Stream;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Class Alert_Type_Email
|
14 |
+
*
|
15 |
+
* @package WP_Stream
|
16 |
+
*/
|
17 |
+
class Alert_Type_Email extends Alert_Type {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Alert type name
|
21 |
+
*
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
public $name = 'Email';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Alert type slug
|
28 |
+
*
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
public $slug = 'email';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Class Constructor
|
35 |
+
*
|
36 |
+
* @param Plugin $plugin Plugin object.
|
37 |
+
* @return void
|
38 |
+
*/
|
39 |
+
public function __construct( $plugin ) {
|
40 |
+
parent::__construct( $plugin );
|
41 |
+
$this->plugin = $plugin;
|
42 |
+
if ( ! is_admin() ) {
|
43 |
+
return;
|
44 |
+
}
|
45 |
+
add_filter( 'wp_stream_alerts_save_meta', array( $this, 'add_alert_meta' ), 10, 2 );
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Sends an email to the given recipient.
|
50 |
+
*
|
51 |
+
* @param int $record_id Record that triggered notification.
|
52 |
+
* @param array $recordarr Record details.
|
53 |
+
* @param Alert $alert Alert options.
|
54 |
+
* @return void
|
55 |
+
*/
|
56 |
+
public function alert( $record_id, $recordarr, $alert ) {
|
57 |
+
$options = wp_parse_args( $alert->alert_meta, array(
|
58 |
+
'email_recipient' => '',
|
59 |
+
'email_subject' => '',
|
60 |
+
'trigger_action' => '',
|
61 |
+
'trigger_connector' => '',
|
62 |
+
'trigger_context' => '',
|
63 |
+
) );
|
64 |
+
|
65 |
+
if ( empty( $options['email_recipient'] ) && empty( $options['email_subject'] ) ) {
|
66 |
+
return;
|
67 |
+
}
|
68 |
+
|
69 |
+
$message = sprintf( __( 'A Stream Alert was triggered on %s.', 'stream' ), get_bloginfo( 'name' ) ) . "\n\n";
|
70 |
+
|
71 |
+
$user_id = $recordarr['user_id'];
|
72 |
+
$user = get_user_by( 'id', $user_id );
|
73 |
+
$message .= sprintf( __( "User:\t%s", 'stream' ), $user->user_login ) . "\n";
|
74 |
+
|
75 |
+
if ( ! empty( $alert->alert_meta['trigger_context'] ) ) {
|
76 |
+
$context = $this->plugin->alerts->alert_triggers['context']->get_display_value( 'list_table', $alert );
|
77 |
+
$message .= sprintf( __( "Context:\t%s", 'stream' ), $context ) . "\n";
|
78 |
+
}
|
79 |
+
if ( ! empty( $alert->alert_meta['trigger_action'] ) ) {
|
80 |
+
$action = $this->plugin->alerts->alert_triggers['action']->get_display_value( 'list_table', $alert );
|
81 |
+
$message .= sprintf( __( "Action:\t%s", 'stream' ), $action ) . "\n";
|
82 |
+
}
|
83 |
+
|
84 |
+
$post = null;
|
85 |
+
if ( isset( $recordarr['object_id'] ) ) {
|
86 |
+
$post_id = $recordarr['object_id'];
|
87 |
+
$post = get_post( $post_id );
|
88 |
+
}
|
89 |
+
if ( is_object( $post ) && ! empty( $post ) ) {
|
90 |
+
$post_type = get_post_type_object( $post->post_type );
|
91 |
+
|
92 |
+
$message .= $post_type->labels->singular_name . ":\t" . $post->post_title . "\n\n";
|
93 |
+
|
94 |
+
$edit_post_link = get_edit_post_link( $post->ID, 'raw' );
|
95 |
+
$message .= sprintf( __( 'Edit %s', 'stream' ), $post_type->labels->singular_name ) . "\n<$edit_post_link>\n";
|
96 |
+
}
|
97 |
+
|
98 |
+
$message .= "\n";
|
99 |
+
|
100 |
+
$edit_alert_link = admin_url( 'edit.php?post_type=wp_stream_alerts#post-' . $alert->ID );
|
101 |
+
$message .= __( 'Edit Alert', 'stream' ) . "\n<$edit_alert_link>";
|
102 |
+
|
103 |
+
wp_mail( $options['email_recipient'], $options['email_subject'], $message );
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Displays a settings form for the alert type
|
108 |
+
*
|
109 |
+
* @param Alert $alert Alert object for the currently displayed alert.
|
110 |
+
* @return void
|
111 |
+
*/
|
112 |
+
public function display_fields( $alert ) {
|
113 |
+
$alert_meta = array();
|
114 |
+
if ( is_object( $alert ) ) {
|
115 |
+
$alert_meta = $alert->alert_meta;
|
116 |
+
}
|
117 |
+
$options = wp_parse_args( $alert_meta, array(
|
118 |
+
'email_recipient' => '',
|
119 |
+
'email_subject' => '',
|
120 |
+
) );
|
121 |
+
|
122 |
+
$form = new Form_Generator;
|
123 |
+
echo '<span class="wp_stream_alert_type_description">' . esc_html__( 'Send a notification email to the recipient.', 'stream' ) . '</span>';
|
124 |
+
echo '<label for="wp_stream_email_recipient"><span class="title">' . esc_html__( 'Recipient', 'stream' ) . '</span>';
|
125 |
+
echo '<span class="input-text-wrap">';
|
126 |
+
echo $form->render_field( 'text', array( // Xss ok.
|
127 |
+
'name' => 'wp_stream_email_recipient',
|
128 |
+
'title' => esc_attr( __( 'Email Recipient', 'stream' ) ),
|
129 |
+
'value' => $options['email_recipient'],
|
130 |
+
) );
|
131 |
+
echo '</span></label>';
|
132 |
+
|
133 |
+
echo '<label for="wp_stream_email_subject"><span class="title">' . esc_html__( 'Subject', 'stream' ) . '</span>';
|
134 |
+
echo '<span class="input-text-wrap">';
|
135 |
+
echo $form->render_field( 'text', array( // Xss ok.
|
136 |
+
'name' => 'wp_stream_email_subject',
|
137 |
+
'title' => esc_attr( __( 'Email Subject', 'stream' ) ),
|
138 |
+
'value' => $options['email_subject'],
|
139 |
+
) );
|
140 |
+
echo '</span></label>';
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Validates and saves form settings for later use.
|
145 |
+
*
|
146 |
+
* @param Alert $alert Alert object for the currently displayed alert.
|
147 |
+
* @return void
|
148 |
+
*/
|
149 |
+
public function save_fields( $alert ) {
|
150 |
+
check_admin_referer( 'save_alert', 'wp_stream_alerts_nonce' );
|
151 |
+
|
152 |
+
if ( isset( $_POST['wp_stream_email_recipient'] ) ) {
|
153 |
+
$alert->alert_meta['email_recipient'] = sanitize_text_field( wp_unslash( $_POST['wp_stream_email_recipient'] ) );
|
154 |
+
}
|
155 |
+
|
156 |
+
if ( isset( $_POST['wp_stream_email_subject'] ) ) {
|
157 |
+
$alert->alert_meta['email_subject'] = sanitize_text_field( wp_unslash( $_POST['wp_stream_email_subject'] ) );
|
158 |
+
}
|
159 |
+
}
|
160 |
+
/**
|
161 |
+
* Add alert meta if this is a highlight alert
|
162 |
+
*
|
163 |
+
* @param array $alert_meta The metadata to be inserted for this alert.
|
164 |
+
* @param string $alert_type The type of alert being added or updated.
|
165 |
+
*
|
166 |
+
* @return mixed
|
167 |
+
*/
|
168 |
+
public function add_alert_meta( $alert_meta, $alert_type ) {
|
169 |
+
if ( $this->slug === $alert_type ) {
|
170 |
+
$email_recipient = wp_stream_filter_input( INPUT_POST, 'wp_stream_email_recipient' );
|
171 |
+
if ( ! empty( $email_recipient ) ) {
|
172 |
+
$alert_meta['email_recipient'] = $email_recipient;
|
173 |
+
}
|
174 |
+
$email_subject = wp_stream_filter_input( INPUT_POST, 'wp_stream_email_subject' );
|
175 |
+
if ( ! empty( $email_subject ) ) {
|
176 |
+
$alert_meta['email_subject'] = $email_subject;
|
177 |
+
}
|
178 |
+
}
|
179 |
+
return $alert_meta;
|
180 |
+
}
|
181 |
+
}
|
alerts/class-alert-type-highlight.php
ADDED
@@ -0,0 +1,301 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Highlight Alert type.
|
4 |
+
*
|
5 |
+
* @package WP_Stream
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace WP_Stream;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Alert_Type_Highlight
|
12 |
+
*
|
13 |
+
* @package WP_Stream
|
14 |
+
*/
|
15 |
+
class Alert_Type_Highlight extends Alert_Type {
|
16 |
+
/**
|
17 |
+
* Main JS file script handle.
|
18 |
+
*/
|
19 |
+
const SCRIPT_HANDLE = 'wp-stream-alert-highlight-js';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Remove Highlight Ajax action label.
|
23 |
+
*/
|
24 |
+
const REMOVE_ACTION = 'stream_remove_highlight';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Remove Action nonce name.
|
28 |
+
*/
|
29 |
+
const REMOVE_ACTION_NONCE = 'stream-remove-highlight';
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Alert type name
|
33 |
+
*
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
public $name = 'Highlight';
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Alert type slug
|
40 |
+
*
|
41 |
+
* @var string
|
42 |
+
*/
|
43 |
+
public $slug = 'highlight';
|
44 |
+
|
45 |
+
/**
|
46 |
+
* The single Alert ID.
|
47 |
+
*
|
48 |
+
* @var int|string
|
49 |
+
*/
|
50 |
+
public $single_alert_id;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* The Plugin
|
54 |
+
*
|
55 |
+
* @var Plugin
|
56 |
+
*/
|
57 |
+
public $plugin;
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Class Constructor
|
61 |
+
*
|
62 |
+
* @param Plugin $plugin Plugin object.
|
63 |
+
* @return void
|
64 |
+
*/
|
65 |
+
public function __construct( $plugin ) {
|
66 |
+
parent::__construct( $plugin );
|
67 |
+
$this->plugin = $plugin;
|
68 |
+
if ( ! is_admin() ) {
|
69 |
+
return;
|
70 |
+
}
|
71 |
+
add_filter( 'wp_stream_record_classes', array( $this, 'post_class' ), 10, 2 );
|
72 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
73 |
+
add_action( 'wp_ajax_' . self::REMOVE_ACTION, array( $this, 'ajax_remove_highlight' ) );
|
74 |
+
|
75 |
+
if ( ! empty( $this->plugin->connectors->connectors ) && is_array( $this->plugin->connectors->connectors ) ) {
|
76 |
+
foreach ( $this->plugin->connectors->connectors as $connector ) {
|
77 |
+
add_filter( 'wp_stream_action_links_' . $connector->name, array( $this, 'action_link_remove_highlight' ), 10, 2 );
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
+
add_filter( 'wp_stream_alerts_save_meta', array( $this, 'add_alert_meta' ), 10, 2 );
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Record that the Alert was triggered by a Record.
|
86 |
+
*
|
87 |
+
* In self::post_class() this value is checked so we can determine
|
88 |
+
* if the class should be added to the Record's display.
|
89 |
+
*
|
90 |
+
* @param int|string $record_id Record that triggered alert.
|
91 |
+
* @param array $recordarr Record details.
|
92 |
+
* @param object $alert Alert options.
|
93 |
+
* @return void
|
94 |
+
*/
|
95 |
+
public function alert( $record_id, $recordarr, $alert ) {
|
96 |
+
$recordarr['ID'] = $record_id;
|
97 |
+
$this->single_alert_id = $alert->ID;
|
98 |
+
if ( ! empty( $alert->alert_meta['color'] ) ) {
|
99 |
+
Alert::update_record_triggered_alerts( (object) $recordarr, $this->slug, array( 'highlight_color' => $alert->alert_meta['color'] ) );
|
100 |
+
}
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Displays a settings form for the alert type
|
105 |
+
*
|
106 |
+
* @param Alert $alert Alert object for the currently displayed alert.
|
107 |
+
* @return void
|
108 |
+
*/
|
109 |
+
public function display_fields( $alert ) {
|
110 |
+
$alert_meta = array();
|
111 |
+
if ( is_object( $alert ) ) {
|
112 |
+
$alert_meta = $alert->alert_meta;
|
113 |
+
}
|
114 |
+
$options = wp_parse_args( $alert_meta, array(
|
115 |
+
'color' => 'yellow',
|
116 |
+
) );
|
117 |
+
|
118 |
+
$form = new Form_Generator;
|
119 |
+
echo '<span class="wp_stream_alert_type_description">' . esc_html__( 'Highlight this alert on the Stream records page.', 'stream' ) . '</span>';
|
120 |
+
echo '<label for="wp_stream_highlight_color"><span class="title">' . esc_html__( 'Color', 'stream' ) . '</span>';
|
121 |
+
echo '<span class="input-text-wrap">';
|
122 |
+
echo $form->render_field( 'select', array( // Xss ok.
|
123 |
+
'name' => 'wp_stream_highlight_color',
|
124 |
+
'title' => esc_attr( __( 'Highlight Color', 'stream' ) ),
|
125 |
+
'options' => $this->get_highlight_options(),
|
126 |
+
'value' => $options['color'],
|
127 |
+
) );
|
128 |
+
echo '</span></label>';
|
129 |
+
}
|
130 |
+
/**
|
131 |
+
* Lists available color options for alerts.
|
132 |
+
*
|
133 |
+
* @return array List of highlight color options.
|
134 |
+
*/
|
135 |
+
public function get_highlight_options() {
|
136 |
+
return array(
|
137 |
+
'yellow' => __( 'Yellow', 'stream' ),
|
138 |
+
'red' => __( 'Red', 'stream' ),
|
139 |
+
'green' => __( 'Green', 'stream' ),
|
140 |
+
'blue' => __( 'Blue', 'stream' ),
|
141 |
+
);
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Validates and saves form settings for later use.
|
146 |
+
*
|
147 |
+
* @param Alert $alert Alert object for the currently displayed alert.
|
148 |
+
* @return void
|
149 |
+
*/
|
150 |
+
public function save_fields( $alert ) {
|
151 |
+
check_admin_referer( 'save_alert', 'wp_stream_alerts_nonce' );
|
152 |
+
|
153 |
+
if ( empty( $_POST['wp_stream_highlight_color'] ) ) {
|
154 |
+
$alert->alert_meta['color'] = 'yellow';
|
155 |
+
}
|
156 |
+
$input_color = sanitize_text_field( wp_unslash( $_POST['wp_stream_highlight_color'] ) );
|
157 |
+
if ( ! array_key_exists( $input_color , $this->get_highlight_options() ) ) {
|
158 |
+
$alert->alert_meta['color'] = 'yellow';
|
159 |
+
} else {
|
160 |
+
$alert->alert_meta['color'] = $input_color;
|
161 |
+
}
|
162 |
+
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Apply highlight to records
|
167 |
+
*
|
168 |
+
* @param array $classes List of classes being applied to the post.
|
169 |
+
* @param object $record Record data.
|
170 |
+
* @return array New list of classes.
|
171 |
+
*/
|
172 |
+
public function post_class( $classes, $record ) {
|
173 |
+
if ( ! empty( $record->meta['wp_stream_alerts_triggered']['highlight']['highlight_color'] ) ) {
|
174 |
+
$color = $record->meta['wp_stream_alerts_triggered']['highlight']['highlight_color'];
|
175 |
+
}
|
176 |
+
|
177 |
+
if ( empty( $color ) || ! is_string( $color ) ) {
|
178 |
+
return $classes;
|
179 |
+
}
|
180 |
+
$classes[] = 'alert-highlight highlight-' . esc_attr( $color ) . ' record-id-' . $record->ID;
|
181 |
+
|
182 |
+
return $classes;
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Maybe add the "Remove Highlight" action link.
|
187 |
+
*
|
188 |
+
* This will appear on highlighted items on
|
189 |
+
* the Record List page.
|
190 |
+
*
|
191 |
+
* This is set to run for all Connectors
|
192 |
+
* in self::__construct().
|
193 |
+
*
|
194 |
+
* @filter wp_stream_action_links_{ connector }
|
195 |
+
*
|
196 |
+
* @param array $actions Action links.
|
197 |
+
* @param object $record A record object.
|
198 |
+
*
|
199 |
+
* @return mixed
|
200 |
+
*/
|
201 |
+
public function action_link_remove_highlight( $actions, $record ) {
|
202 |
+
$record = new Record( $record );
|
203 |
+
$alerts_triggered = $record->get_meta( Alerts::ALERTS_TRIGGERED_META_KEY, true );
|
204 |
+
if ( ! empty( $alerts_triggered[ $this->slug ] ) ) {
|
205 |
+
$actions[ __( 'Remove Highlight', 'stream' ) ] = '#';
|
206 |
+
}
|
207 |
+
|
208 |
+
return $actions;
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Ajax action to remove highlight.
|
213 |
+
*
|
214 |
+
* This is fired from the "Remove Highlight"
|
215 |
+
* action links on the Records list page.
|
216 |
+
*
|
217 |
+
* First, we validate and sanitize.
|
218 |
+
*
|
219 |
+
* Then, we get the Record meta and remove
|
220 |
+
* the "highlight" array from the
|
221 |
+
* "Alerts triggered" meta field.
|
222 |
+
*
|
223 |
+
* Finally, the meta field is updated.
|
224 |
+
*
|
225 |
+
* Note: this removes ALL highlights
|
226 |
+
* that were triggered by this record, not just
|
227 |
+
* those triggered on specific Alert (post) IDs.
|
228 |
+
*
|
229 |
+
* @action wp_ajax_stream_remove_highlight
|
230 |
+
*/
|
231 |
+
public function ajax_remove_highlight() {
|
232 |
+
check_ajax_referer( self::REMOVE_ACTION_NONCE, 'security' );
|
233 |
+
|
234 |
+
$failure_message = __( 'Removing Highlight Failed', 'stream' );
|
235 |
+
|
236 |
+
if ( empty( $_POST['recordId'] ) ) {
|
237 |
+
wp_send_json_error( $failure_message );
|
238 |
+
}
|
239 |
+
|
240 |
+
$record_id = sanitize_text_field( wp_unslash( $_POST['recordId'] ) );
|
241 |
+
|
242 |
+
if ( ! is_numeric( $record_id ) ) {
|
243 |
+
wp_send_json_error( $failure_message );
|
244 |
+
}
|
245 |
+
$record_obj = new \stdClass();
|
246 |
+
$record_obj->ID = $record_id;
|
247 |
+
$record = new Record( $record_obj );
|
248 |
+
$alerts_triggered = $record->get_meta( Alerts::ALERTS_TRIGGERED_META_KEY, true );
|
249 |
+
if ( isset( $alerts_triggered[ $this->slug ] ) ) {
|
250 |
+
unset( $alerts_triggered[ $this->slug ] );
|
251 |
+
}
|
252 |
+
$record->update_meta( Alerts::ALERTS_TRIGGERED_META_KEY, $alerts_triggered );
|
253 |
+
wp_send_json_success();
|
254 |
+
}
|
255 |
+
|
256 |
+
/**
|
257 |
+
* Enqueue Highlight-specific scripts.
|
258 |
+
*
|
259 |
+
* @param string $page WP admin page.
|
260 |
+
*/
|
261 |
+
public function enqueue_scripts( $page ) {
|
262 |
+
if ( 'toplevel_page_wp_stream' === $page ) {
|
263 |
+
wp_register_script( self::SCRIPT_HANDLE, $this->plugin->locations['url'] . 'alerts/js/alert-type-highlight.js', array( 'jquery' ) );
|
264 |
+
|
265 |
+
$exports = array(
|
266 |
+
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
|
267 |
+
'removeAction' => self::REMOVE_ACTION,
|
268 |
+
'security' => wp_create_nonce( self::REMOVE_ACTION_NONCE ),
|
269 |
+
);
|
270 |
+
|
271 |
+
wp_scripts()->add_data(
|
272 |
+
self::SCRIPT_HANDLE,
|
273 |
+
'data',
|
274 |
+
sprintf( 'var _streamAlertTypeHighlightExports = %s;', wp_json_encode( $exports ) )
|
275 |
+
);
|
276 |
+
|
277 |
+
wp_add_inline_script( self::SCRIPT_HANDLE, 'streamAlertTypeHighlight.init();', 'after' );
|
278 |
+
wp_enqueue_script( self::SCRIPT_HANDLE );
|
279 |
+
}
|
280 |
+
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Add alert meta if this is a highlight alert
|
284 |
+
*
|
285 |
+
* @param array $alert_meta The metadata to be inserted for this alert.
|
286 |
+
* @param string $alert_type The type of alert being added or updated.
|
287 |
+
*
|
288 |
+
* @return mixed
|
289 |
+
*/
|
290 |
+
public function add_alert_meta( $alert_meta, $alert_type ) {
|
291 |
+
if ( $this->slug === $alert_type ) {
|
292 |
+
$color = wp_stream_filter_input( INPUT_POST, 'wp_stream_highlight_color' );
|
293 |
+
if ( empty( $color ) ) {
|
294 |
+
$alert_meta['color'] = 'yellow';
|
295 |
+
} else {
|
296 |
+
$alert_meta['color'] = $color;
|
297 |
+
}
|
298 |
+
}
|
299 |
+
return $alert_meta;
|
300 |
+
}
|
301 |
+
}
|
alerts/class-alert-type-ifttt.php
ADDED
@@ -0,0 +1,307 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* If This Then That (IFTTT) Alert type.
|
4 |
+
*
|
5 |
+
* A user must create a IFTTT Maker account,
|
6 |
+
* and get their Maker Key, found here:
|
7 |
+
*
|
8 |
+
* @link https://ifttt.com/maker
|
9 |
+
* This will be used in the Stream Alert form.
|
10 |
+
*
|
11 |
+
* Next, they create a new recipe, using the
|
12 |
+
* "Maker" > "Receive a web request" trigger.
|
13 |
+
* @link https://ifttt.com/myrecipes/personal/new
|
14 |
+
*
|
15 |
+
* Here, they will enter a label for the event name.
|
16 |
+
* This will be also need to be entered into the Stream Alert form.
|
17 |
+
*
|
18 |
+
* Finally, the Maker Key and Event Name need to be entered into
|
19 |
+
* the Alert metabox.
|
20 |
+
*
|
21 |
+
* This class uses the above data to send at POST request to IFTTT,
|
22 |
+
* which then hooks into whichever service the user has determined
|
23 |
+
* in their Recipe.
|
24 |
+
*
|
25 |
+
* Notes:
|
26 |
+
*
|
27 |
+
* In their IFTTT recipe, the Task Content field "quicktags" are
|
28 |
+
* defined as such in the unfiltered state of this Alert Type:
|
29 |
+
*
|
30 |
+
* {{EventName}} - The name the user assigned to this event.
|
31 |
+
* {{Value1}} - The Record Summary
|
32 |
+
* {{Value2}} - The User that triggered the alert
|
33 |
+
* {{Value3}} - The date/time on which the alert was triggered.
|
34 |
+
*
|
35 |
+
* There are several filters in self::notify_ifttt() that
|
36 |
+
* allow for complete customization of these values.
|
37 |
+
*
|
38 |
+
* More info:
|
39 |
+
* @link https://ifttt.com/channels/maker/triggers/1636368624-receive-a-web-request
|
40 |
+
*
|
41 |
+
* @package WP_Stream
|
42 |
+
*/
|
43 |
+
|
44 |
+
namespace WP_Stream;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Class Alert_Type_IFTTT
|
48 |
+
*
|
49 |
+
* @package WP_Stream
|
50 |
+
*/
|
51 |
+
class Alert_Type_IFTTT extends Alert_Type {
|
52 |
+
/**
|
53 |
+
* Alert type name
|
54 |
+
*
|
55 |
+
* @var string
|
56 |
+
*/
|
57 |
+
public $name = 'IFTTT';
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Alert type slug
|
61 |
+
*
|
62 |
+
* @var string
|
63 |
+
*/
|
64 |
+
public $slug = 'ifttt';
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Class Constructor
|
68 |
+
*
|
69 |
+
* @param Plugin $plugin Plugin object.
|
70 |
+
* @return void
|
71 |
+
*/
|
72 |
+
public function __construct( $plugin ) {
|
73 |
+
parent::__construct( $plugin );
|
74 |
+
$this->plugin = $plugin;
|
75 |
+
if ( ! is_admin() ) {
|
76 |
+
return;
|
77 |
+
}
|
78 |
+
add_filter( 'wp_stream_alerts_save_meta', array( $this, 'add_alert_meta' ), 10, 2 );
|
79 |
+
}
|
80 |
+
/**
|
81 |
+
* Record that the Alert was triggered by a Record.
|
82 |
+
*
|
83 |
+
* In self::post_class() this value is checked so we can determine
|
84 |
+
* if the class should be added to the Record's display.
|
85 |
+
*
|
86 |
+
* @param int|string $record_id Record that triggered alert.
|
87 |
+
* @param array $recordarr Record details.
|
88 |
+
* @param object $alert Alert options.
|
89 |
+
* @return void
|
90 |
+
*/
|
91 |
+
public function alert( $record_id, $recordarr, $alert ) {
|
92 |
+
$recordarr['ID'] = $record_id;
|
93 |
+
$this->notify_ifttt( $alert, $recordarr );
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Displays a settings form for the alert type
|
98 |
+
*
|
99 |
+
* @param Alert $alert Alert object for the currently displayed alert.
|
100 |
+
* @return void
|
101 |
+
*/
|
102 |
+
public function display_fields( $alert ) {
|
103 |
+
$alert_meta = array();
|
104 |
+
if ( is_object( $alert ) ) {
|
105 |
+
$alert_meta = $alert->alert_meta;
|
106 |
+
}
|
107 |
+
$options = wp_parse_args( $alert_meta, array(
|
108 |
+
'maker_key' => '',
|
109 |
+
'event_name' => '',
|
110 |
+
) );
|
111 |
+
|
112 |
+
$form = new Form_Generator;
|
113 |
+
|
114 |
+
echo '<span class="wp_stream_alert_type_description">';
|
115 |
+
echo esc_html__( 'Trigger an IFTTT Maker recipe.', 'stream' );
|
116 |
+
echo wp_kses_post( sprintf( ' (<a href="%1$s" target="_blank">%2$s</span></a>)', 'https://youtu.be/XFWtkHXv9h0', __( 'Tutorial', 'stream' ) ) );
|
117 |
+
echo '</span>';
|
118 |
+
echo '<label for="wp_stream_ifttt_maker_key"><span class="title">' . esc_html__( 'Maker Key', 'stream' ) . '</span>';
|
119 |
+
echo '<span class="input-text-wrap">';
|
120 |
+
echo $form->render_field( 'text', array( // Xss ok.
|
121 |
+
'name' => 'wp_stream_ifttt_maker_key',
|
122 |
+
'title' => esc_attr( __( 'Maker Key', 'stream' ) ),
|
123 |
+
'value' => $options['maker_key'],
|
124 |
+
) );
|
125 |
+
echo '</span>';
|
126 |
+
printf(
|
127 |
+
'<span class="input-text-wrap"><a href="%1$s" target="_blank">%2$s %3$s</a></span>',
|
128 |
+
esc_url( 'https://ifttt.com/maker' ),
|
129 |
+
esc_html__( 'Open IFTTT Maker Channel', 'stream' ),
|
130 |
+
'<span class="dashicons dashicons-external"></span>'
|
131 |
+
);
|
132 |
+
echo '</label>';
|
133 |
+
|
134 |
+
echo '<label for="wp_stream_ifttt_event_name"><span class="title">' . esc_html__( 'Event Name', 'stream' ) . '</span>';
|
135 |
+
echo '<span class="input-text-wrap">';
|
136 |
+
echo $form->render_field( 'text', array( // Xss ok.
|
137 |
+
'name' => 'wp_stream_ifttt_event_name',
|
138 |
+
'title' => esc_attr( __( 'Event Name', 'stream' ) ),
|
139 |
+
'value' => $options['event_name'],
|
140 |
+
) );
|
141 |
+
echo '</span>';
|
142 |
+
printf(
|
143 |
+
'<span class="input-text-wrap"><a href="%1$s" target="_blank">%2$s %3$s</a></span>',
|
144 |
+
esc_url( 'https://ifttt.com/myrecipes/personal' ),
|
145 |
+
esc_html__( 'Open IFTTT Recipes', 'stream' ),
|
146 |
+
'<span class="dashicons dashicons-external"></span>'
|
147 |
+
);
|
148 |
+
echo '</label>';
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Validates and saves form settings for later use.
|
153 |
+
*
|
154 |
+
* @param Alert $alert Alert object for the currently displayed alert.
|
155 |
+
* @return void
|
156 |
+
*/
|
157 |
+
public function save_fields( $alert ) {
|
158 |
+
check_admin_referer( 'save_alert', 'wp_stream_alerts_nonce' );
|
159 |
+
$alert->alert_meta['maker_key'] = '';
|
160 |
+
|
161 |
+
if ( ! empty( $_POST['wp_stream_ifttt_maker_key'] ) ) {
|
162 |
+
$alert->alert_meta['maker_key'] = sanitize_text_field( wp_unslash( $_POST['wp_stream_ifttt_maker_key'] ) );
|
163 |
+
}
|
164 |
+
if ( ! empty( $_POST['wp_stream_ifttt_event_name'] ) ) {
|
165 |
+
$alert->alert_meta['event_name'] = sanitize_text_field( wp_unslash( $_POST['wp_stream_ifttt_event_name'] ) );
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Send a POST request to IFTTT.
|
171 |
+
*
|
172 |
+
* This method sends Record data to IFTTT for processing.
|
173 |
+
*
|
174 |
+
* There are several filters here (documented below) that
|
175 |
+
* allow for customization of the data sent.
|
176 |
+
*
|
177 |
+
* Note that IFTTT only allows for three specifically-named
|
178 |
+
* array keys of data. (also documented below)
|
179 |
+
*
|
180 |
+
* @param object $alert The Alert object.
|
181 |
+
* @param array $recordarr Array of Record data.
|
182 |
+
*
|
183 |
+
* @return bool
|
184 |
+
*/
|
185 |
+
public function notify_ifttt( $alert, $recordarr ) {
|
186 |
+
if ( empty( $alert->alert_meta['maker_key'] ) || empty( $alert->alert_meta['event_name'] ) || empty( $recordarr ) ) {
|
187 |
+
return false;
|
188 |
+
}
|
189 |
+
|
190 |
+
$record_data = wp_parse_args( $recordarr, array(
|
191 |
+
'summary' => sprintf( __( 'The event %s was triggered' ), $alert->alert_meta['event_name'] ),
|
192 |
+
'user_id' => get_current_user_id(),
|
193 |
+
'created' => current_time( 'Y-m-d H:i:s' ), // Blog's local time.
|
194 |
+
) );
|
195 |
+
|
196 |
+
$user_id = $recordarr['user_id'];
|
197 |
+
$user = get_user_by( 'id', $user_id );
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Filter User data field
|
201 |
+
*
|
202 |
+
* Defaults to 'user_login'.
|
203 |
+
*
|
204 |
+
* @param object $alert The Alert.
|
205 |
+
* @param array $recordarray The Record's data.
|
206 |
+
* @return string
|
207 |
+
*/
|
208 |
+
$user_field = apply_filters( 'wp_stream_alert_ifttt_user_data_value', 'user_login', $alert, $recordarr );
|
209 |
+
$user_value = ! empty( $user->$user_field ) ? $user->$user_field : $user->user_login;
|
210 |
+
|
211 |
+
$created = $recordarr['created'];
|
212 |
+
/**
|
213 |
+
* Filter the date format string
|
214 |
+
*
|
215 |
+
* Defaults to 'Y-m-d H:i:s'.
|
216 |
+
*
|
217 |
+
* @param object $alert The Alert.
|
218 |
+
* @param array $recordarray The Record's data.
|
219 |
+
* @return string
|
220 |
+
*/
|
221 |
+
$date_format = apply_filters( 'wp_stream_alert_ifttt_date_format', 'Y-m-d H:i:s', $alert, $recordarr );
|
222 |
+
$date = date( $date_format, strtotime( $created ) );
|
223 |
+
|
224 |
+
$url = 'https://maker.ifttt.com/trigger/' . $alert->alert_meta['event_name'] . '/with/key/' . $alert->alert_meta['maker_key'];
|
225 |
+
|
226 |
+
/*
|
227 |
+
* The array key labels for the request body are required by
|
228 |
+
* IFTTT; their names cannot be changed.
|
229 |
+
*
|
230 |
+
* The filter defaults are set up to send:
|
231 |
+
* value1 = Record Summary
|
232 |
+
*
|
233 |
+
* value2 = User login name
|
234 |
+
* (see the wp_stream_alert_ifttt_user_data_value filter above)
|
235 |
+
*
|
236 |
+
* value3 = Record Date
|
237 |
+
* (see the wp_stream_alert_ifttt_date_format filter above)
|
238 |
+
*
|
239 |
+
* The filters below allow complete customization of these data values.
|
240 |
+
*/
|
241 |
+
$args = array(
|
242 |
+
'headers' => array(
|
243 |
+
'Content-Type' => 'application/json',
|
244 |
+
),
|
245 |
+
'body' => wp_json_encode(
|
246 |
+
array(
|
247 |
+
/**
|
248 |
+
* Filter the first IFTTT alert value
|
249 |
+
*
|
250 |
+
* @param string $summary The Record's summary.
|
251 |
+
* @param object $alert The Alert.
|
252 |
+
* @param array $recordarr Array of Record data.
|
253 |
+
* @return mixed
|
254 |
+
*/
|
255 |
+
'value1' => apply_filters( 'wp_stream_alert_ifttt_value_one', $record_data['summary'], $alert, $recordarr ),
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Filter the second IFTTT alert value
|
259 |
+
*
|
260 |
+
* @param string $user_value The user meta value requested above.
|
261 |
+
* @param int $user_id The user ID who fired the Alert.
|
262 |
+
* @param object $alert The Alert.
|
263 |
+
* @param array $recordarr Array of Record data.
|
264 |
+
* @return mixed
|
265 |
+
*/
|
266 |
+
'value2' => apply_filters( 'wp_stream_alert_ifttt_value_two', $user_value, $user_id, $alert, $recordarr ),
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Filter the third IFTTT alert value
|
270 |
+
*
|
271 |
+
* @param string $date The Record's date.
|
272 |
+
* @param object $alert The Alert.
|
273 |
+
* @param array $recordarr Array of Record data.
|
274 |
+
* @return mixed
|
275 |
+
*/
|
276 |
+
'value3' => apply_filters( 'wp_stream_alert_ifttt_value_three', $date, $alert, $recordarr ),
|
277 |
+
)
|
278 |
+
),
|
279 |
+
);
|
280 |
+
$response = wp_remote_post( $url, $args );
|
281 |
+
if ( ! is_array( $response ) ) {
|
282 |
+
return false;
|
283 |
+
}
|
284 |
+
return true;
|
285 |
+
}
|
286 |
+
/**
|
287 |
+
* Add alert meta if this is a highlight alert
|
288 |
+
*
|
289 |
+
* @param array $alert_meta The metadata to be inserted for this alert.
|
290 |
+
* @param string $alert_type The type of alert being added or updated.
|
291 |
+
*
|
292 |
+
* @return mixed
|
293 |
+
*/
|
294 |
+
public function add_alert_meta( $alert_meta, $alert_type ) {
|
295 |
+
if ( $this->slug === $alert_type ) {
|
296 |
+
$maker_key = wp_stream_filter_input( INPUT_POST, 'wp_stream_ifttt_maker_key' );
|
297 |
+
if ( ! empty( $maker_key ) ) {
|
298 |
+
$alert_meta['maker_key'] = $maker_key;
|
299 |
+
}
|
300 |
+
$event_name = wp_stream_filter_input( INPUT_POST, 'wp_stream_ifttt_event_name' );
|
301 |
+
if ( ! empty( $event_name ) ) {
|
302 |
+
$alert_meta['event_name'] = $event_name;
|
303 |
+
}
|
304 |
+
}
|
305 |
+
return $alert_meta;
|
306 |
+
}
|
307 |
+
}
|
alerts/class-alert-type-menu-alert.php
ADDED
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Menu Alert type.
|
4 |
+
*
|
5 |
+
* @package WP_Stream
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace WP_Stream;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Alert_Type_Menu_Alert
|
12 |
+
*
|
13 |
+
* @package WP_Stream
|
14 |
+
*/
|
15 |
+
class Alert_Type_Menu_Alert extends Alert_Type {
|
16 |
+
/**
|
17 |
+
* Alert type name
|
18 |
+
*
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
public $name = 'Create Menu Alert';
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Alert type slug
|
25 |
+
*
|
26 |
+
* @var string
|
27 |
+
*/
|
28 |
+
public $slug = 'menu-alert';
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Class Constructor
|
32 |
+
*
|
33 |
+
* @param Plugin $plugin Plugin object.
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
+
public function __construct( $plugin ) {
|
37 |
+
parent::__construct( $plugin );
|
38 |
+
add_action( 'admin_bar_menu', array( $this, 'menu_alert' ), 99 );
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Notify user of triggered alert.
|
43 |
+
*
|
44 |
+
* @param int $record_id Record that triggered alert.
|
45 |
+
* @param array $recordarr Record details.
|
46 |
+
* @param array $options Alert options.
|
47 |
+
* @return void
|
48 |
+
*/
|
49 |
+
public function alert( $record_id, $recordarr, $options ) {
|
50 |
+
$this->add_message( $recordarr['summary'] );
|
51 |
+
return;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Displays a settings form for the alert type
|
56 |
+
*
|
57 |
+
* @param Alert $alert Alert object for the currently displayed alert.
|
58 |
+
* @return void
|
59 |
+
*/
|
60 |
+
public function display_fields( $alert ) {
|
61 |
+
$alert_meta = array();
|
62 |
+
if ( is_object( $alert ) ) {
|
63 |
+
$alert_meta = $alert->alert_meta;
|
64 |
+
}
|
65 |
+
$options = wp_parse_args( $alert_meta, array(
|
66 |
+
'clear_immediate' => false,
|
67 |
+
) );
|
68 |
+
|
69 |
+
$form = new Form_Generator;
|
70 |
+
$form->add_field( 'checkbox', array(
|
71 |
+
'name' => 'wp_stream_menu_alert_clear_immediate',
|
72 |
+
'text' => esc_attr( __( 'Clear alerts after seen.', 'stream' ) ),
|
73 |
+
'value' => $options['clear_immediate'],
|
74 |
+
'title' => __( 'Menu Bar', 'stream' ),
|
75 |
+
) );
|
76 |
+
|
77 |
+
echo $form->render_all(); // Xss ok.
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Validates and saves form settings for later use.
|
82 |
+
*
|
83 |
+
* @param Alert $alert Alert object for the currently displayed alert.
|
84 |
+
* @return void
|
85 |
+
*/
|
86 |
+
public function save_fields( $alert ) {
|
87 |
+
check_admin_referer( 'save_alert', 'wp_stream_alerts_nonce' );
|
88 |
+
|
89 |
+
$alert->alert_meta['clear_immediate'] = ! empty( $_POST['wp_stream_menu_alert_clear_immediate'] );
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Display and clear all unviewed menu alerts
|
94 |
+
*
|
95 |
+
* @param WP_Admin_Bar $wp_admin_bar Representation of the WP Admin Bar.
|
96 |
+
* @return bool True if notifications were displayed, false otherwise.
|
97 |
+
*/
|
98 |
+
public function menu_alert( $wp_admin_bar ) {
|
99 |
+
$messages = $this->get_messages();
|
100 |
+
if ( ! $messages ) {
|
101 |
+
return false;
|
102 |
+
}
|
103 |
+
|
104 |
+
$wp_admin_bar->add_node( array(
|
105 |
+
'id' => 'wp_stream_alert_notify',
|
106 |
+
'parent' => false,
|
107 |
+
'title' => __( 'New Stream Alert', 'stream' ),
|
108 |
+
'href' => '#',
|
109 |
+
'meta' => array( 'class' => 'opposite' ),
|
110 |
+
) );
|
111 |
+
|
112 |
+
foreach ( $messages as $key => $message ) {
|
113 |
+
$wp_admin_bar->add_node( array(
|
114 |
+
'id' => 'wp_stream_alert_notify_' . $key,
|
115 |
+
'parent' => 'wp_stream_alert_notify',
|
116 |
+
'title' => esc_html( $message ),
|
117 |
+
'href' => '#',
|
118 |
+
'meta' => array( 'class' => 'opposite' ),
|
119 |
+
) );
|
120 |
+
}
|
121 |
+
|
122 |
+
$this->clear_messages();
|
123 |
+
return true;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Get a list of all current alert messages for current user.
|
128 |
+
*
|
129 |
+
* @todo update this for VIP. (get_user_meta)
|
130 |
+
*
|
131 |
+
* @return array List of alert messages
|
132 |
+
*/
|
133 |
+
public function get_messages() {
|
134 |
+
$current_user = wp_get_current_user();
|
135 |
+
$messages = get_user_meta( $current_user->ID, $this->get_key(), false );
|
136 |
+
return $messages;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Adds a new alert message for the current user.
|
141 |
+
*
|
142 |
+
* @todo update this for VIP. (add_user_meta)
|
143 |
+
*
|
144 |
+
* @param string $message Alert message to add.
|
145 |
+
* @return void
|
146 |
+
*/
|
147 |
+
public function add_message( $message ) {
|
148 |
+
$current_user = wp_get_current_user();
|
149 |
+
add_user_meta( $current_user->ID, $this->get_key(), $message, false );
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Clears all alert messages for the current user.
|
154 |
+
*
|
155 |
+
* @todo update this for VIP. (delete_user_meta)
|
156 |
+
*
|
157 |
+
* @param bool $global Whether to clear globally.
|
158 |
+
* @return void
|
159 |
+
*/
|
160 |
+
public function clear_messages( $global = false ) {
|
161 |
+
$current_user = wp_get_current_user();
|
162 |
+
delete_user_meta( $current_user->ID, $this->get_key(), $global );
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Returns meta key for pending alerts.
|
167 |
+
*
|
168 |
+
* @return string Meta key
|
169 |
+
*/
|
170 |
+
public function get_key() {
|
171 |
+
return 'wp_stream_alerts_menu_pending';
|
172 |
+
}
|
173 |
+
}
|
alerts/class-alert-type-none.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* "Do nothing" Alert type.
|
4 |
+
*
|
5 |
+
* @package WP_Stream
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace WP_Stream;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Alert_Type_None
|
12 |
+
*
|
13 |
+
* @package WP_Stream
|
14 |
+
*/
|
15 |
+
class Alert_Type_None extends Alert_Type {
|
16 |
+
/**
|
17 |
+
* Notifier name
|
18 |
+
*
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
public $name = 'Do Nothing';
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Notifier slug
|
25 |
+
*
|
26 |
+
* @var string
|
27 |
+
*/
|
28 |
+
public $slug = 'none';
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Does not notify user.
|
32 |
+
*
|
33 |
+
* @param int $record_id Record that triggered alert.
|
34 |
+
* @param array $recordarr Record details.
|
35 |
+
* @param array $options Alert options.
|
36 |
+
* @return void
|
37 |
+
*/
|
38 |
+
public function alert( $record_id, $recordarr, $options ) {
|
39 |
+
return;
|
40 |
+
}
|
41 |
+
}
|
alerts/js/alert-type-highlight.js
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* globals jQuery, _streamAlertTypeHighlightExports */
|
2 |
+
/* exported streamAlertTypeHighlight */
|
3 |
+
var streamAlertTypeHighlight = ( function( $ ) {
|
4 |
+
var self = {
|
5 |
+
ajaxUrl: '',
|
6 |
+
removeAction: '',
|
7 |
+
security: ''
|
8 |
+
};
|
9 |
+
|
10 |
+
if ( 'undefined' !== typeof _streamAlertTypeHighlightExports ) {
|
11 |
+
$.extend( self, _streamAlertTypeHighlightExports );
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* The primary function for this file.
|
16 |
+
*
|
17 |
+
* @returns void.
|
18 |
+
*/
|
19 |
+
self.init = function() {
|
20 |
+
$( document ).ready( function() {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Remove highlights on Record list screen.
|
24 |
+
*
|
25 |
+
* @returns void.
|
26 |
+
*/
|
27 |
+
$( '.alert-highlight .action-link[href="#"]' ).each( function() {
|
28 |
+
var actionLink = $( this );
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Ajax call to remove the highlight.
|
32 |
+
*
|
33 |
+
* @returns void.
|
34 |
+
*/
|
35 |
+
actionLink.click( function( e ) {
|
36 |
+
var recordId, data;
|
37 |
+
e.preventDefault();
|
38 |
+
recordId = actionLink.parents( '.alert-highlight' ).attr( 'class' ).match( /record\-id\-[\w-]*\b/ );
|
39 |
+
recordId = recordId[0].replace( 'record-id-', '' );
|
40 |
+
|
41 |
+
data = {
|
42 |
+
action: self.removeAction,
|
43 |
+
security: self.security,
|
44 |
+
recordId: recordId
|
45 |
+
};
|
46 |
+
|
47 |
+
$.post( self.ajaxUrl, data, function( response ) {
|
48 |
+
if ( true === response.success ) {
|
49 |
+
ajaxDone();
|
50 |
+
}
|
51 |
+
});
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Fires when Ajax complete.
|
55 |
+
*/
|
56 |
+
function ajaxDone() {
|
57 |
+
var row = actionLink.parents( '.alert-highlight' ),
|
58 |
+
odd = $( '.striped > tbody > :nth-child( odd )' );
|
59 |
+
if ( row.is( odd ) ) {
|
60 |
+
row.animate( { backgroundColor: '#f9f9f9' }, 300, function() {
|
61 |
+
row.removeClass( 'alert-highlight' );
|
62 |
+
});
|
63 |
+
} else {
|
64 |
+
row.animate( { backgroundColor: '' }, 300, function() {
|
65 |
+
row.removeClass( 'alert-highlight' );
|
66 |
+
});
|
67 |
+
}
|
68 |
+
actionLink.remove();
|
69 |
+
}
|
70 |
+
});
|
71 |
+
});
|
72 |
+
}); // End document.ready().
|
73 |
+
};
|
74 |
+
|
75 |
+
return self;
|
76 |
+
|
77 |
+
})( jQuery );
|
classes/class-admin.php
CHANGED
@@ -299,6 +299,14 @@ class Admin {
|
|
299 |
$main_menu_position
|
300 |
);
|
301 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
302 |
/**
|
303 |
* Filter the Settings admin page title
|
304 |
*
|
@@ -433,6 +441,11 @@ class Admin {
|
|
433 |
return true;
|
434 |
}
|
435 |
|
|
|
|
|
|
|
|
|
|
|
436 |
return false;
|
437 |
}
|
438 |
|
@@ -615,7 +628,7 @@ class Admin {
|
|
615 |
$options = (array) get_option( 'wp_stream', array() );
|
616 |
}
|
617 |
|
618 |
-
if (
|
619 |
return;
|
620 |
}
|
621 |
|
299 |
$main_menu_position
|
300 |
);
|
301 |
|
302 |
+
/**
|
303 |
+
* Fires before submenu items are added to the Stream menu
|
304 |
+
* allowing plugins to add menu items before Settings
|
305 |
+
*
|
306 |
+
* @return void
|
307 |
+
*/
|
308 |
+
do_action( 'wp_stream_admin_menu' );
|
309 |
+
|
310 |
/**
|
311 |
* Filter the Settings admin page title
|
312 |
*
|
441 |
return true;
|
442 |
}
|
443 |
|
444 |
+
$screen = get_current_screen();
|
445 |
+
if ( is_admin() && 'post' === $screen->base && Alerts::POST_TYPE === $screen->post_type ) {
|
446 |
+
return true;
|
447 |
+
}
|
448 |
+
|
449 |
return false;
|
450 |
}
|
451 |
|
628 |
$options = (array) get_option( 'wp_stream', array() );
|
629 |
}
|
630 |
|
631 |
+
if ( ! empty( $options['general_keep_records_indefinitely'] ) || ! isset( $options['general_records_ttl'] ) ) {
|
632 |
return;
|
633 |
}
|
634 |
|
classes/class-alert-trigger.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Alert Trigger abstract class.
|
4 |
+
*
|
5 |
+
* @package WP_Stream
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace WP_Stream;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Alert_Trigger
|
12 |
+
*
|
13 |
+
* @package WP_Stream
|
14 |
+
*/
|
15 |
+
abstract class Alert_Trigger {
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Hold the Plugin class
|
19 |
+
*
|
20 |
+
* @var Plugin
|
21 |
+
*/
|
22 |
+
public $plugin;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Unique identifier
|
26 |
+
*
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
public $slug;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Class constructor
|
33 |
+
*
|
34 |
+
* @param Plugin $plugin Plugin class.
|
35 |
+
*/
|
36 |
+
public function __construct( $plugin ) {
|
37 |
+
$this->plugin = $plugin;
|
38 |
+
|
39 |
+
add_action( 'wp_stream_alert_trigger_form_display', array( $this, 'add_fields' ), 10, 2 );
|
40 |
+
add_action( 'wp_stream_alert_trigger_form_save', array( $this, 'save_fields' ), 10, 1 );
|
41 |
+
add_filter( 'wp_stream_alert_trigger_check', array( $this, 'check_record' ), 10, 4 );
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Checks if a record matches the criteria from the trigger.
|
46 |
+
*
|
47 |
+
* @filter wp_stream_alert_trigger_check
|
48 |
+
*
|
49 |
+
* @param bool $success Status of previous checks.
|
50 |
+
* @param int $record_id Record ID.
|
51 |
+
* @param array $recordarr Record data.
|
52 |
+
* @param Alert $alert The Alert being worked on.
|
53 |
+
* @return bool False on failure, otherwise should return original value of $success.
|
54 |
+
*/
|
55 |
+
abstract public function check_record ( $success, $record_id, $recordarr, $alert );
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Adds fields to the trigger form.
|
59 |
+
*
|
60 |
+
* @action wp_stream_alert_trigger_form_display
|
61 |
+
*
|
62 |
+
* @param Form_Generator $form The Form Object to add to.
|
63 |
+
* @param Alert $alert The Alert being worked on.
|
64 |
+
* @return void
|
65 |
+
*/
|
66 |
+
abstract public function add_fields( $form, $alert );
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Validate and save Alert object
|
70 |
+
*
|
71 |
+
* @action wp_stream_alert_trigger_form_save
|
72 |
+
*
|
73 |
+
* @param Alert $alert The Alert being worked on.
|
74 |
+
* @return void
|
75 |
+
*/
|
76 |
+
abstract public function save_fields( $alert );
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Returns the trigger's value for the given alert.
|
80 |
+
*
|
81 |
+
* @param string $context The location this data will be displayed in.
|
82 |
+
* @param Alert $alert Alert being processed.
|
83 |
+
* @return string
|
84 |
+
*/
|
85 |
+
abstract public function get_display_value( $context = 'normal', $alert );
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Allow connectors to determine if their dependencies is satisfied or not
|
89 |
+
*
|
90 |
+
* @return bool
|
91 |
+
*/
|
92 |
+
public function is_dependency_satisfied() {
|
93 |
+
return true;
|
94 |
+
}
|
95 |
+
}
|
classes/class-alert-type.php
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Alert Type abstract class.
|
4 |
+
*
|
5 |
+
* Used to register new Alert types.
|
6 |
+
*
|
7 |
+
* @package WP_Stream
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace WP_Stream;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Class Alert_Type
|
14 |
+
*
|
15 |
+
* @package WP_Stream
|
16 |
+
*/
|
17 |
+
abstract class Alert_Type {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Hold the Plugin class
|
21 |
+
*
|
22 |
+
* @var Plugin
|
23 |
+
*/
|
24 |
+
public $plugin;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Unique identifier.
|
28 |
+
*
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
public $slug;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Class constructor.
|
35 |
+
*
|
36 |
+
* @param Plugin $plugin Plugin object.
|
37 |
+
* @return void
|
38 |
+
*/
|
39 |
+
public function __construct( $plugin ) {
|
40 |
+
$this->plugin = $plugin;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Alert recipients about the new record
|
45 |
+
*
|
46 |
+
* @param int $record_id Record ID.
|
47 |
+
* @param array $recordarr Record details.
|
48 |
+
* @param array $options Alert options.
|
49 |
+
*/
|
50 |
+
abstract public function alert( $record_id, $recordarr, $options );
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Display settings form for configuration of individual alerts
|
54 |
+
*
|
55 |
+
* @param Alert $alert Alert currently being worked on.
|
56 |
+
*/
|
57 |
+
public function display_fields( $alert ) {
|
58 |
+
return;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Process settings form for configuration of individual alerts
|
63 |
+
*
|
64 |
+
* @param Alert $alert Alert currently being worked on.
|
65 |
+
*/
|
66 |
+
public function save_fields( $alert ) {
|
67 |
+
return;
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Allow connectors to determine if their dependencies are satisfied or not
|
72 |
+
*
|
73 |
+
* @return bool
|
74 |
+
*/
|
75 |
+
public function is_dependency_satisfied() {
|
76 |
+
return true;
|
77 |
+
}
|
78 |
+
}
|
classes/class-alert.php
ADDED
@@ -0,0 +1,337 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Single Alert handler.
|
4 |
+
*
|
5 |
+
* @package WP_Stream
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace WP_Stream;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Alert
|
12 |
+
*
|
13 |
+
* @package WP_Stream
|
14 |
+
*/
|
15 |
+
class Alert {
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Alert post ID
|
19 |
+
*
|
20 |
+
* @var int
|
21 |
+
*/
|
22 |
+
public $ID;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Creation date
|
26 |
+
*
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
public $date;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Status
|
33 |
+
*
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
public $status;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Alert author ID
|
40 |
+
*
|
41 |
+
* @var int
|
42 |
+
*/
|
43 |
+
public $author;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Alert type
|
47 |
+
*
|
48 |
+
* @var string
|
49 |
+
*/
|
50 |
+
public $alert_type;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Alert meta data
|
54 |
+
*
|
55 |
+
* @var int
|
56 |
+
*/
|
57 |
+
public $alert_meta;
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Hold Plugin class
|
61 |
+
*
|
62 |
+
* @var Plugin
|
63 |
+
*/
|
64 |
+
public $plugin;
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Class constructor
|
68 |
+
*
|
69 |
+
* @param object $item Alert data.
|
70 |
+
* @param Plugin $plugin Plugin class.
|
71 |
+
* @return void
|
72 |
+
*/
|
73 |
+
public function __construct( $item, $plugin ) {
|
74 |
+
$this->plugin = $plugin;
|
75 |
+
|
76 |
+
$this->ID = isset( $item->ID ) ? $item->ID : null;
|
77 |
+
$this->status = isset( $item->status ) ? $item->status : 'wp_stream_disabled';
|
78 |
+
$this->date = isset( $item->date ) ? $item->date : null;
|
79 |
+
$this->author = isset( $item->author ) ? $item->author : null;
|
80 |
+
|
81 |
+
$this->alert_type = isset( $item->alert_type ) ? $item->alert_type : null;
|
82 |
+
$this->alert_meta = isset( $item->alert_meta ) ? $item->alert_meta : array();
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Save state of the Alert to database
|
87 |
+
*
|
88 |
+
* @return int The Post ID of the alert.
|
89 |
+
*/
|
90 |
+
public function save() {
|
91 |
+
|
92 |
+
$args = array(
|
93 |
+
'ID' => $this->ID,
|
94 |
+
'post_date' => $this->date,
|
95 |
+
'post_status' => $this->status,
|
96 |
+
'post_content' => '',
|
97 |
+
'post_title' => $this->get_title(),
|
98 |
+
'post_author' => $this->author,
|
99 |
+
'post_type' => Alerts::POST_TYPE,
|
100 |
+
);
|
101 |
+
|
102 |
+
if ( empty( $args['ID'] ) ) {
|
103 |
+
unset( $args['ID'] );
|
104 |
+
}
|
105 |
+
|
106 |
+
$post_id = wp_insert_post( $args );
|
107 |
+
if ( empty( $args['ID'] ) ) {
|
108 |
+
$this->ID = $post_id;
|
109 |
+
}
|
110 |
+
|
111 |
+
$meta = array(
|
112 |
+
'alert_type' => $this->alert_type,
|
113 |
+
'alert_meta' => $this->alert_meta,
|
114 |
+
);
|
115 |
+
|
116 |
+
foreach ( $meta as $key => $value ) {
|
117 |
+
$this->update_meta( $key, $value );
|
118 |
+
}
|
119 |
+
|
120 |
+
return $post_id;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Process settings form data
|
125 |
+
*
|
126 |
+
* @param array $data Processed post object data.
|
127 |
+
* @return array New post object data.
|
128 |
+
*/
|
129 |
+
public function process_settings_form( $data ) {
|
130 |
+
|
131 |
+
$args = array(
|
132 |
+
'post_date' => $this->date,
|
133 |
+
'post_status' => $this->status,
|
134 |
+
'post_title' => $this->get_title(),
|
135 |
+
'post_author' => $this->author,
|
136 |
+
'post_type' => Alerts::POST_TYPE,
|
137 |
+
);
|
138 |
+
|
139 |
+
foreach ( $args as $key => $value ) {
|
140 |
+
$data[ $key ] = $value;
|
141 |
+
}
|
142 |
+
|
143 |
+
$meta_input = array(
|
144 |
+
'alert_type' => $this->alert_type,
|
145 |
+
'alert_meta' => $this->alert_meta,
|
146 |
+
);
|
147 |
+
|
148 |
+
foreach ( $meta_input as $key => $value ) {
|
149 |
+
$this->update_meta( $key, $value );
|
150 |
+
}
|
151 |
+
|
152 |
+
return $data;
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Query record meta
|
157 |
+
*
|
158 |
+
* @param string $meta_key Meta key to retrieve (optional). Otherwise will
|
159 |
+
* grab all meta data for the ID.
|
160 |
+
* @param bool $single Whether to only retrieve the first value (optional).
|
161 |
+
*
|
162 |
+
* @return mixed Single value if $single is true, array if false.
|
163 |
+
*/
|
164 |
+
public function get_meta( $meta_key = '', $single = false ) {
|
165 |
+
return maybe_unserialize( get_post_meta( $this->ID, $meta_key, $single ) );
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Update record meta
|
170 |
+
*
|
171 |
+
* @param string $meta_key Meta key to update.
|
172 |
+
* @param string $meta_value Value to update with.
|
173 |
+
* @param string $prev_value Previous value to change (optional).
|
174 |
+
* @return array
|
175 |
+
*/
|
176 |
+
public function update_meta( $meta_key, $meta_value, $prev_value = '' ) {
|
177 |
+
return update_post_meta( $this->ID, $meta_key, $meta_value, $prev_value );
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Determine the title of the alert.
|
182 |
+
*
|
183 |
+
* @todo enhance human readibility
|
184 |
+
* @return string The title of the alert
|
185 |
+
*/
|
186 |
+
function get_title() {
|
187 |
+
|
188 |
+
$alert_type = $this->get_alert_type_obj()->name;
|
189 |
+
|
190 |
+
$output = array();
|
191 |
+
foreach ( array( 'action', 'author', 'context' ) as $trigger_type ) {
|
192 |
+
$output[ $trigger_type ] = $this->plugin->alerts->alert_triggers[ $trigger_type ]->get_display_value( 'list_table', $this );
|
193 |
+
}
|
194 |
+
$title = '';
|
195 |
+
foreach ( $this->plugin->alerts->alert_triggers as $trigger_type => $trigger_obj ) {
|
196 |
+
$value = $trigger_obj->get_display_value( 'list_table', $this );
|
197 |
+
$title .= $value . ' > ';
|
198 |
+
}
|
199 |
+
$title = rtrim( $title, ' > ' );
|
200 |
+
return $title;
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Retrive current alert type object
|
205 |
+
*
|
206 |
+
* @return Alert_Type
|
207 |
+
*/
|
208 |
+
public function get_alert_type_obj() {
|
209 |
+
if ( array_key_exists( $this->alert_type, $this->plugin->alerts->alert_types ) ) {
|
210 |
+
$obj = $this->plugin->alerts->alert_types[ $this->alert_type ];
|
211 |
+
} else {
|
212 |
+
$obj = new Alert_Type_None( $this->plugin );
|
213 |
+
}
|
214 |
+
return $obj;
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Check if record matches trigger criteria.
|
219 |
+
*
|
220 |
+
* @param int $record_id Record ID.
|
221 |
+
* @param array $recordarr Record data.
|
222 |
+
* @return bool True if a positive match. False otherwise.
|
223 |
+
*/
|
224 |
+
public function check_record( $record_id, $recordarr ) {
|
225 |
+
return apply_filters( 'wp_stream_alert_trigger_check', true, $record_id, $recordarr, $this );
|
226 |
+
}
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Trigger alert for a specific record.
|
230 |
+
*
|
231 |
+
* @param int $record_id Record ID.
|
232 |
+
* @param int $recordarr Record Data.
|
233 |
+
* @return void
|
234 |
+
*/
|
235 |
+
public function send_alert( $record_id, $recordarr ) {
|
236 |
+
$this->get_alert_type_obj()->alert( $record_id, $recordarr, $this );
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Record Alerts triggered by a Record.
|
241 |
+
*
|
242 |
+
* This should be used any time an alert is triggered.
|
243 |
+
*
|
244 |
+
* Stores the post ID of an Alert triggered by a record.
|
245 |
+
*
|
246 |
+
* As an example, this exists so that its value(s) can then be used
|
247 |
+
* to fetch meta from that Alert in later operations.
|
248 |
+
*
|
249 |
+
* This also creates the Alert triggered meta if not found.
|
250 |
+
*
|
251 |
+
* @see Alert_Type_Highlight::alert() for an example.
|
252 |
+
*
|
253 |
+
* @param object $record The Record.
|
254 |
+
* @param string $alert_slug The Alert Type slug.
|
255 |
+
* @param array $alert_meta Alert meta.
|
256 |
+
*
|
257 |
+
* @return bool If the meta was updated successfully.
|
258 |
+
*/
|
259 |
+
public static function update_record_triggered_alerts( $record, $alert_slug, $alert_meta ) {
|
260 |
+
if ( ! is_string( $alert_slug ) ) {
|
261 |
+
return false;
|
262 |
+
}
|
263 |
+
|
264 |
+
if ( is_array( $record ) ) {
|
265 |
+
$record = (object) $record;
|
266 |
+
}
|
267 |
+
if ( empty( $record->ID ) ) {
|
268 |
+
return false;
|
269 |
+
}
|
270 |
+
$record = new Record( $record );
|
271 |
+
$alerts_triggered = $record->get_meta( Alerts::ALERTS_TRIGGERED_META_KEY, true );
|
272 |
+
|
273 |
+
if ( empty( $alerts_triggered ) || ! is_array( $alerts_triggered ) ) {
|
274 |
+
$alerts_triggered = array( $alert_slug => $alert_meta );
|
275 |
+
} elseif ( ! array_key_exists( $alert_slug, $alerts_triggered ) || ! is_array( $alerts_triggered[ $alert_slug ] ) ) {
|
276 |
+
$alerts_triggered[ $alert_slug ] = $alert_meta;
|
277 |
+
}
|
278 |
+
return $record->update_meta( Alerts::ALERTS_TRIGGERED_META_KEY, $alerts_triggered );
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* Get a meta value from the Alert that a Record has triggered.
|
283 |
+
*
|
284 |
+
* If a Record has triggered an Alert (post), this fetches a specific
|
285 |
+
* Alert meta (i.e., "post meta") value from that Alert.
|
286 |
+
*
|
287 |
+
* First, it gets the array of Alerts that the Record has triggered.
|
288 |
+
* Then, using the requested Alert Type, it grabs the first item (post ID) in
|
289 |
+
* that Type.
|
290 |
+
*
|
291 |
+
* Using that ID, it fetches that Alert post's meta, then
|
292 |
+
* returns the value of the requested setting (ie., "post meta" field).
|
293 |
+
*
|
294 |
+
* @see Alert_Type_Highlight::post_class() for an example.
|
295 |
+
*
|
296 |
+
* @param object $record The Record object.
|
297 |
+
* @param string $alert_slug The slug of the Alert Type.
|
298 |
+
* @param string $setting The requested meta value of the Alert.
|
299 |
+
* @param mixed $default The default value if no value is found.
|
300 |
+
*
|
301 |
+
* @return mixed
|
302 |
+
*/
|
303 |
+
public function get_single_alert_setting_from_record( $record, $alert_slug, $setting, $default = false ) {
|
304 |
+
if ( ! is_object( $record ) || ! is_string( $alert_slug ) || ! is_string( $setting ) ) {
|
305 |
+
return false;
|
306 |
+
}
|
307 |
+
$record = new Record( $record );
|
308 |
+
$alerts_triggered = $record->get_meta( Alerts::ALERTS_TRIGGERED_META_KEY, true );
|
309 |
+
|
310 |
+
// Ensure we have a meta array and that this record has triggered a highlight alert.
|
311 |
+
if ( empty( $alerts_triggered ) || ! is_array( $alerts_triggered ) || ! array_key_exists( $alert_slug, $alerts_triggered ) ) {
|
312 |
+
return false;
|
313 |
+
}
|
314 |
+
|
315 |
+
$values = $alerts_triggered[ $alert_slug ];
|
316 |
+
if ( empty( $values ) ) {
|
317 |
+
return false;
|
318 |
+
}
|
319 |
+
|
320 |
+
// Grab an Alert post ID.
|
321 |
+
// @todo determine which Alert post takes priority.
|
322 |
+
if ( is_array( $values ) ) {
|
323 |
+
$post_id = $values[0];
|
324 |
+
} else {
|
325 |
+
$post_id = $values;
|
326 |
+
}
|
327 |
+
|
328 |
+
if ( ! is_numeric( $post_id ) ) {
|
329 |
+
return false;
|
330 |
+
}
|
331 |
+
|
332 |
+
$alert = $this->plugin->alerts->get_alert( $post_id );
|
333 |
+
|
334 |
+
$value = ! empty( $alert->alert_meta[ $setting ] ) ? $alert->alert_meta[ $setting ] : $default;
|
335 |
+
return $value;
|
336 |
+
}
|
337 |
+
}
|
classes/class-alerts-list.php
ADDED
@@ -0,0 +1,374 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Listing of Alerts in the WP Admin.
|
4 |
+
*
|
5 |
+
* @package WP_Stream
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace WP_Stream;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Alerts_List
|
12 |
+
*
|
13 |
+
* @package WP_Stream
|
14 |
+
*/
|
15 |
+
class Alerts_List {
|
16 |
+
/**
|
17 |
+
* Hold the Plugin class
|
18 |
+
*
|
19 |
+
* @var Plugin
|
20 |
+
*/
|
21 |
+
public $plugin;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Class constructor.
|
25 |
+
*
|
26 |
+
* @param Plugin $plugin The main Plugin class.
|
27 |
+
*/
|
28 |
+
public function __construct( $plugin ) {
|
29 |
+
$this->plugin = $plugin;
|
30 |
+
|
31 |
+
add_filter( 'bulk_actions-edit-wp_stream_alerts', array( $this, 'suppress_bulk_actions' ), 10, 1 );
|
32 |
+
add_filter( 'disable_months_dropdown', array( $this, 'suppress_months_dropdown' ), 10, 2 );
|
33 |
+
add_filter( 'post_row_actions', array( $this, 'suppress_quick_edit' ), 10, 1 );
|
34 |
+
|
35 |
+
// @todo Make more specific
|
36 |
+
if ( is_admin() ) {
|
37 |
+
add_filter( 'request', array( $this, 'parse_request' ), 10, 2 );
|
38 |
+
}
|
39 |
+
add_filter( 'views_edit-wp_stream_alerts', array( $this, 'manage_views' ) );
|
40 |
+
|
41 |
+
add_filter( 'manage_wp_stream_alerts_posts_columns', array( $this, 'manage_columns' ) );
|
42 |
+
add_action( 'manage_wp_stream_alerts_posts_custom_column', array( $this, 'column_data' ), 10, 2 );
|
43 |
+
|
44 |
+
add_action( 'quick_edit_custom_box', array( $this, 'display_custom_quick_edit' ), 10, 2 );
|
45 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
46 |
+
|
47 |
+
add_filter( 'wp_insert_post_data', array( $this, 'save_alert_inline_edit' ), 99, 2 );
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Default to wp_stream_enabled and wp_stream_disabled when querying for alerts
|
52 |
+
*
|
53 |
+
* @filter request
|
54 |
+
*
|
55 |
+
* @param array $query_vars Arguments for query to populate table.
|
56 |
+
* @return array
|
57 |
+
*/
|
58 |
+
function parse_request( $query_vars ) {
|
59 |
+
$screen = get_current_screen();
|
60 |
+
if ( 'edit-wp_stream_alerts' === $screen->id && Alerts::POST_TYPE === $query_vars['post_type'] && empty( $query_vars['post_status'] ) ) {
|
61 |
+
$query_vars['post_status'] = array( 'wp_stream_enabled', 'wp_stream_disabled' );
|
62 |
+
}
|
63 |
+
return $query_vars;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Manage views on the alerts list view
|
68 |
+
*
|
69 |
+
* @filter views_edit-wp_stream_alerts
|
70 |
+
*
|
71 |
+
* @param array $views View links HTML.
|
72 |
+
* @return array
|
73 |
+
*/
|
74 |
+
function manage_views( $views ) {
|
75 |
+
|
76 |
+
if ( array_key_exists( 'trash', $views ) ) {
|
77 |
+
$trash = $views['trash'];
|
78 |
+
unset( $views['trash'] );
|
79 |
+
$views['trash'] = $trash;
|
80 |
+
}
|
81 |
+
|
82 |
+
return $views;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Manages columns on the alerts list view
|
87 |
+
*
|
88 |
+
* @filter manage_wp_stream_alerts_posts_columns
|
89 |
+
*
|
90 |
+
* @param array $columns Column id -> title array.
|
91 |
+
* @return array
|
92 |
+
*/
|
93 |
+
function manage_columns( $columns ) {
|
94 |
+
$columns = array(
|
95 |
+
'cb' => $columns['cb'],
|
96 |
+
'alert_trigger' => __( 'Trigger', 'stream' ),
|
97 |
+
'alert_type' => __( 'Type', 'stream' ),
|
98 |
+
'alert_status' => __( 'Status', 'stream' ),
|
99 |
+
);
|
100 |
+
return $columns;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Fills in column data for custom columns.
|
105 |
+
*
|
106 |
+
* @action manage_wp_stream_alerts_posts_custom_column
|
107 |
+
*
|
108 |
+
* @param string $column_name Column name to show data for.
|
109 |
+
* @param int $post_id The post being processed.
|
110 |
+
* @return mixed
|
111 |
+
*/
|
112 |
+
function column_data( $column_name, $post_id ) {
|
113 |
+
|
114 |
+
$alert = $this->plugin->alerts->get_alert( $post_id );
|
115 |
+
if ( ! $alert ) {
|
116 |
+
return;
|
117 |
+
}
|
118 |
+
|
119 |
+
switch ( $column_name ) {
|
120 |
+
case 'alert_trigger' :
|
121 |
+
$values = array();
|
122 |
+
foreach ( $this->plugin->alerts->alert_triggers as $trigger_type => $trigger_obj ) {
|
123 |
+
$value = $trigger_obj->get_display_value( 'list_table', $alert );
|
124 |
+
$values[] = '<span class="alert_trigger_value alert_trigger_' . esc_attr( $trigger_type ) . '">' . esc_html( $value ) . '</span>';
|
125 |
+
}
|
126 |
+
?>
|
127 |
+
<div><?php echo wp_kses_post( join( '', $values ) ); ?></div>
|
128 |
+
<div class="row-actions wp-stream-show-mobile">
|
129 |
+
<?php echo wp_kses_post( $this->custom_column_actions( $post_id ) ); ?>
|
130 |
+
<button type="button" class="toggle-row"><span class="screen-reader-text"><?php echo esc_html__( 'Show more details', 'stream' ); ?></span></button>
|
131 |
+
</div>
|
132 |
+
<?php
|
133 |
+
if ( ! empty( $alert->alert_meta['trigger_connector'] ) ) {
|
134 |
+
$trigger_connector = $alert->alert_meta['trigger_connector'];
|
135 |
+
} else {
|
136 |
+
$trigger_connector = '';
|
137 |
+
}
|
138 |
+
if ( ! empty( $alert->alert_meta['trigger_context'] ) ) {
|
139 |
+
$trigger_context = $alert->alert_meta['trigger_context'];
|
140 |
+
} else {
|
141 |
+
$trigger_context = '';
|
142 |
+
}
|
143 |
+
if ( ! empty( $alert->alert_meta['trigger_action'] ) ) {
|
144 |
+
$trigger_action = $alert->alert_meta['trigger_action'];
|
145 |
+
} else {
|
146 |
+
$trigger_action = '';
|
147 |
+
}
|
148 |
+
?>
|
149 |
+
<input type="hidden" name="wp_stream_trigger_connector" value="<?php echo esc_attr( $trigger_connector ); ?>" />
|
150 |
+
<input type="hidden" name="wp_stream_trigger_context" value="<?php echo esc_attr( $trigger_context ); ?>" />
|
151 |
+
<input type="hidden" name="wp_stream_trigger_action" value="<?php echo esc_attr( $trigger_action ); ?>" />
|
152 |
+
<?php
|
153 |
+
echo wp_kses_post( $this->custom_column_actions( $post_id ) );
|
154 |
+
break;
|
155 |
+
case 'alert_type' :
|
156 |
+
$alert_type = $alert->alert_type;
|
157 |
+
if ( ! empty( $this->plugin->alerts->alert_types[ $alert_type ]->name ) ) {
|
158 |
+
$alert_name = $this->plugin->alerts->alert_types[ $alert_type ]->name;
|
159 |
+
} else {
|
160 |
+
$alert_name = 'Untitled Alert';
|
161 |
+
}
|
162 |
+
?>
|
163 |
+
<input type="hidden" name="wp_stream_alert_type" value="<?php echo esc_attr( $alert->alert_type ); ?>" />
|
164 |
+
<strong class="row-title"><?php echo esc_html( $alert_name ); ?></strong>
|
165 |
+
<?php
|
166 |
+
if ( ! empty( $alert->alert_meta['color'] ) ) {
|
167 |
+
?>
|
168 |
+
<input type="hidden" name="wp_stream_highlight_color" value="<?php echo esc_attr( $alert->alert_meta['color'] ); ?>" />
|
169 |
+
<?php
|
170 |
+
}
|
171 |
+
if ( ! empty( $alert->alert_meta['email_recipient'] ) ) {
|
172 |
+
?>
|
173 |
+
<input type="hidden" name="wp_stream_email_recipient" value="<?php echo esc_attr( $alert->alert_meta['email_recipient'] ); ?>" />
|
174 |
+
<?php
|
175 |
+
}
|
176 |
+
if ( ! empty( $alert->alert_meta['email_subject'] ) ) {
|
177 |
+
?>
|
178 |
+
<input type="hidden" name="wp_stream_email_subject" value="<?php echo esc_attr( $alert->alert_meta['email_subject'] ); ?>" />
|
179 |
+
<?php
|
180 |
+
}
|
181 |
+
if ( ! empty( $alert->alert_meta['event_name'] ) ) {
|
182 |
+
?>
|
183 |
+
<input type="hidden" name="wp_stream_ifttt_event_name" value="<?php echo esc_attr( $alert->alert_meta['event_name'] ); ?>" />
|
184 |
+
<?php
|
185 |
+
}
|
186 |
+
if ( ! empty( $alert->alert_meta['maker_key'] ) ) {
|
187 |
+
?>
|
188 |
+
<input type="hidden" name="wp_stream_ifttt_maker_key" value="<?php echo esc_attr( $alert->alert_meta['maker_key'] ); ?>" />
|
189 |
+
<?php
|
190 |
+
}
|
191 |
+
break;
|
192 |
+
case 'alert_status' :
|
193 |
+
$post_status_object = get_post_status_object( get_post_status( $post_id ) );
|
194 |
+
if ( ! empty( $post_status_object ) ) {
|
195 |
+
echo esc_html( $post_status_object->label );
|
196 |
+
}
|
197 |
+
?>
|
198 |
+
<input type="hidden" name="wp_stream_alert_status" value="<?php echo esc_attr( $post_status_object->name ); ?>" />
|
199 |
+
<?php
|
200 |
+
break;
|
201 |
+
}
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Remove 'edit' action from bulk actions
|
206 |
+
*
|
207 |
+
* @filter bulk_actions-edit-wp_stream_alerts
|
208 |
+
*
|
209 |
+
* @param array $actions List of bulk actions available.
|
210 |
+
* @return array
|
211 |
+
*/
|
212 |
+
public function suppress_bulk_actions( $actions ) {
|
213 |
+
unset( $actions['edit'] );
|
214 |
+
return $actions;
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Remove quick edit action from inline edit actions
|
219 |
+
*
|
220 |
+
* @filter post_row_actions
|
221 |
+
*
|
222 |
+
* @param array $actions List of inline edit actions available.
|
223 |
+
* @return array
|
224 |
+
*/
|
225 |
+
function suppress_quick_edit( $actions ) {
|
226 |
+
if ( Alerts::POST_TYPE !== get_post_type() ) {
|
227 |
+
return $actions;
|
228 |
+
}
|
229 |
+
unset( $actions['edit'] );
|
230 |
+
unset( $actions['view'] );
|
231 |
+
unset( $actions['trash'] );
|
232 |
+
unset( $actions['inline hide-if-no-js'] );
|
233 |
+
return $actions;
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Remove months dropdown from Alerts list page
|
238 |
+
*
|
239 |
+
* @filter disable_months_dropdown
|
240 |
+
*
|
241 |
+
* @param bool $status Status of months dropdown enabling.
|
242 |
+
* @param string $post_type Post type status is related to.
|
243 |
+
* @return bool
|
244 |
+
*/
|
245 |
+
public function suppress_months_dropdown( $status, $post_type ) {
|
246 |
+
if ( Alerts::POST_TYPE === $post_type ) {
|
247 |
+
$status = true;
|
248 |
+
}
|
249 |
+
return $status;
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Custom column actions for alerts main screen
|
254 |
+
*
|
255 |
+
* @param int $post_id The current post ID.
|
256 |
+
*
|
257 |
+
* @return string
|
258 |
+
*/
|
259 |
+
public function custom_column_actions( $post_id ) {
|
260 |
+
$post_status = wp_stream_filter_input( INPUT_GET, 'post_status' );
|
261 |
+
ob_start();
|
262 |
+
if ( 'trash' !== $post_status ) {
|
263 |
+
$bare_url = admin_url( 'post.php?post=' . $post_id . '&action=trash' );
|
264 |
+
$nonce_url = wp_nonce_url( $bare_url, 'trash-post_' . $post_id );
|
265 |
+
?>
|
266 |
+
<div class="row-actions">
|
267 |
+
<span class="inline hide-if-no-js"><a href="#" class="editinline" aria-label="Quick edit “Hello world!” inline"><?php esc_html_e( 'Edit' ); ?></a> | </span>
|
268 |
+
<span class="trash">
|
269 |
+
<a href="<?php echo esc_url( $nonce_url ); ?>" class="submitdelete"><?php esc_html_e( 'Trash', 'stream' ); ?></a>
|
270 |
+
</span>
|
271 |
+
</div>
|
272 |
+
<?php
|
273 |
+
}
|
274 |
+
return ob_get_clean();
|
275 |
+
}
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Display a custom quick edit form.
|
279 |
+
*/
|
280 |
+
public function display_custom_quick_edit() {
|
281 |
+
static $fired = false;
|
282 |
+
if ( false !== $fired ) {
|
283 |
+
return;
|
284 |
+
}
|
285 |
+
$screen = get_current_screen();
|
286 |
+
if ( 'edit-wp_stream_alerts' !== $screen->id ) {
|
287 |
+
return;
|
288 |
+
}
|
289 |
+
wp_nonce_field( plugin_basename( __FILE__ ), Alerts::POST_TYPE . '_edit_nonce' );
|
290 |
+
$box_type = array(
|
291 |
+
'triggers',
|
292 |
+
'notification',
|
293 |
+
'submit',
|
294 |
+
);
|
295 |
+
?>
|
296 |
+
<legend class="inline-edit-legend"><?php esc_html_e( 'Edit', 'stream' ); ?></legend>
|
297 |
+
<?php
|
298 |
+
foreach ( $box_type as $type ) : // @todo remove inline styles. ?>
|
299 |
+
<fieldset class="inline-edit-col inline-edit-<?php echo esc_attr( Alerts::POST_TYPE ); ?>">
|
300 |
+
<?php
|
301 |
+
$function_name = 'display_' . $type . '_box';
|
302 |
+
$the_post = get_post();
|
303 |
+
call_user_func( array( $this->plugin->alerts, $function_name ), $the_post );
|
304 |
+
?>
|
305 |
+
</fieldset>
|
306 |
+
<?php
|
307 |
+
endforeach;
|
308 |
+
$fired = true;
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Enqueue scripts for the alerts list screen.
|
313 |
+
*
|
314 |
+
* @param string $page The current page name.
|
315 |
+
*/
|
316 |
+
public function enqueue_scripts( $page ) {
|
317 |
+
$screen = get_current_screen();
|
318 |
+
if ( 'edit-wp_stream_alerts' !== $screen->id ) {
|
319 |
+
return;
|
320 |
+
}
|
321 |
+
wp_register_script( 'wp-stream-alerts-list-js', $this->plugin->locations['url'] . 'ui/js/alerts-list.js', array( 'wp-stream-alerts', 'jquery' ) );
|
322 |
+
wp_enqueue_script( 'wp-stream-alerts-list-js' );
|
323 |
+
wp_register_style( 'wp-stream-alerts-list-css', $this->plugin->locations['url'] . 'ui/css/alerts-list.css' );
|
324 |
+
wp_enqueue_style( 'wp-stream-alerts-list-css' );
|
325 |
+
wp_enqueue_style( 'wp-stream-select2' );
|
326 |
+
}
|
327 |
+
|
328 |
+
/**
|
329 |
+
* Save alert meta after using the inline editor.
|
330 |
+
*
|
331 |
+
* @param array $data Filtered post data.
|
332 |
+
* @param array $postarr Raw post data.
|
333 |
+
*
|
334 |
+
* @return array
|
335 |
+
*/
|
336 |
+
function save_alert_inline_edit( $data, $postarr ) {
|
337 |
+
$post_id = $postarr['ID'];
|
338 |
+
$post_type = wp_stream_filter_input( INPUT_POST, 'post_type' );
|
339 |
+
if ( Alerts::POST_TYPE !== $post_type ) {
|
340 |
+
return $data;
|
341 |
+
}
|
342 |
+
if ( ! current_user_can( 'edit_post', $post_id ) ) {
|
343 |
+
return $data;
|
344 |
+
}
|
345 |
+
|
346 |
+
$nonce = wp_stream_filter_input( INPUT_POST, Alerts::POST_TYPE . '_edit_nonce' );
|
347 |
+
if ( null === $nonce || ! wp_verify_nonce( $nonce, plugin_basename( __FILE__ ) ) ) {
|
348 |
+
return $data;
|
349 |
+
}
|
350 |
+
|
351 |
+
$trigger_author = wp_stream_filter_input( INPUT_POST, 'wp_stream_trigger_author' );
|
352 |
+
$trigger_connector_and_context = wp_stream_filter_input( INPUT_POST, 'wp_stream_trigger_connector_or_context' );
|
353 |
+
$trigger_connector_and_context_split = explode( '-', $trigger_connector_and_context );
|
354 |
+
$trigger_connector = $trigger_connector_and_context_split[0];
|
355 |
+
$trigger_context = $trigger_connector_and_context_split[1];
|
356 |
+
|
357 |
+
$trigger_action = wp_stream_filter_input( INPUT_POST, 'wp_stream_trigger_action' );
|
358 |
+
$alert_type = wp_stream_filter_input( INPUT_POST, 'wp_stream_alert_type' );
|
359 |
+
$alert_status = wp_stream_filter_input( INPUT_POST, 'wp_stream_alert_status' );
|
360 |
+
$data['post_status'] = $alert_status;
|
361 |
+
|
362 |
+
update_post_meta( $post_id, 'alert_type', $alert_type );
|
363 |
+
|
364 |
+
$alert_meta = array(
|
365 |
+
'trigger_author' => $trigger_author,
|
366 |
+
'trigger_connector' => $trigger_connector,
|
367 |
+
'trigger_action' => $trigger_action,
|
368 |
+
'trigger_context' => $trigger_context,
|
369 |
+
);
|
370 |
+
$alert_meta = apply_filters( 'wp_stream_alerts_save_meta', $alert_meta, $alert_type );
|
371 |
+
update_post_meta( $post_id, 'alert_meta', $alert_meta );
|
372 |
+
return $data;
|
373 |
+
}
|
374 |
+
}
|
classes/class-alerts.php
ADDED
@@ -0,0 +1,777 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Alerts feature class.
|
4 |
+
*
|
5 |
+
* @package WP_Stream
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace WP_Stream;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Alerts
|
12 |
+
*
|
13 |
+
* @package WP_Stream
|
14 |
+
*/
|
15 |
+
class Alerts {
|
16 |
+
/**
|
17 |
+
* Alerts post type slug
|
18 |
+
*/
|
19 |
+
const POST_TYPE = 'wp_stream_alerts';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Triggered Alerts meta key for Records
|
23 |
+
*/
|
24 |
+
const ALERTS_TRIGGERED_META_KEY = 'wp_stream_alerts_triggered';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Hold Plugin class
|
28 |
+
*
|
29 |
+
* @var Plugin
|
30 |
+
*/
|
31 |
+
public $plugin;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Post meta prefix
|
35 |
+
*
|
36 |
+
* @var string
|
37 |
+
*/
|
38 |
+
public $meta_prefix = 'wp_stream';
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Alert Types
|
42 |
+
*
|
43 |
+
* @var array
|
44 |
+
*/
|
45 |
+
public $alert_types = array();
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Alert Triggers
|
49 |
+
*
|
50 |
+
* @var array
|
51 |
+
*/
|
52 |
+
public $alert_triggers = array();
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Class constructor.
|
56 |
+
*
|
57 |
+
* @param Plugin $plugin The main Plugin class.
|
58 |
+
*/
|
59 |
+
public function __construct( $plugin ) {
|
60 |
+
$this->plugin = $plugin;
|
61 |
+
|
62 |
+
// Register custom post type.
|
63 |
+
add_action( 'init', array( $this, 'register_post_type' ) );
|
64 |
+
|
65 |
+
// Add custom post type to menu.
|
66 |
+
add_action( 'wp_stream_admin_menu', array( $this, 'register_menu' ) );
|
67 |
+
|
68 |
+
// Add scripts to post screens.
|
69 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'register_scripts' ) );
|
70 |
+
|
71 |
+
add_action( 'network_admin_menu', array( $this, 'change_menu_link_url' ), 99 );
|
72 |
+
|
73 |
+
add_filter( 'wp_stream_record_inserted', array( $this, 'check_records' ), 10, 2 );
|
74 |
+
|
75 |
+
add_action( 'wp_ajax_load_alerts_settings', array( $this, 'load_alerts_settings' ) );
|
76 |
+
add_action( 'wp_ajax_get_actions', array( $this, 'get_actions' ) );
|
77 |
+
add_action( 'wp_ajax_save_new_alert', array( $this, 'save_new_alert' ) );
|
78 |
+
add_action( 'wp_ajax_get_new_alert_triggers_notifications', array(
|
79 |
+
$this,
|
80 |
+
'get_new_alert_triggers_notifications',
|
81 |
+
) );
|
82 |
+
|
83 |
+
$this->load_alert_types();
|
84 |
+
$this->load_alert_triggers();
|
85 |
+
|
86 |
+
add_filter( 'wp_stream_action_links_posts', array( $this, 'change_alert_action_links' ), 11, 2 );
|
87 |
+
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Load alert_type classes
|
92 |
+
*
|
93 |
+
* @return void
|
94 |
+
*/
|
95 |
+
function load_alert_types() {
|
96 |
+
$alert_types = array(
|
97 |
+
'none',
|
98 |
+
'highlight',
|
99 |
+
'email',
|
100 |
+
'ifttt',
|
101 |
+
);
|
102 |
+
|
103 |
+
$classes = array();
|
104 |
+
foreach ( $alert_types as $alert_type ) {
|
105 |
+
$file_location = $this->plugin->locations['dir'] . '/alerts/class-alert-type-' . $alert_type . '.php';
|
106 |
+
if ( file_exists( $file_location ) ) {
|
107 |
+
include_once $file_location;
|
108 |
+
$class_name = sprintf( '\WP_Stream\Alert_Type_%s', str_replace( '-', '_', $alert_type ) );
|
109 |
+
if ( ! class_exists( $class_name ) ) {
|
110 |
+
continue;
|
111 |
+
}
|
112 |
+
$class = new $class_name( $this->plugin );
|
113 |
+
if ( ! property_exists( $class, 'slug' ) ) {
|
114 |
+
continue;
|
115 |
+
}
|
116 |
+
$classes[ $class->slug ] = $class;
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Allows for adding additional alert_types via classes that extend Notifier.
|
122 |
+
*
|
123 |
+
* @param array $classes An array of Notifier objects. In the format alert_type_slug => Notifier_Class()
|
124 |
+
*/
|
125 |
+
$this->alert_types = apply_filters( 'wp_stream_alert_types', $classes );
|
126 |
+
|
127 |
+
// Ensure that all alert_types extend Notifier.
|
128 |
+
foreach ( $this->alert_types as $key => $alert_type ) {
|
129 |
+
if ( ! $this->is_valid_alert_type( $alert_type ) ) {
|
130 |
+
unset( $this->alert_types[ $key ] );
|
131 |
+
trigger_error(
|
132 |
+
sprintf(
|
133 |
+
esc_html__( 'Registered alert_type %s does not extend WP_Stream\Alert_Type.', 'stream' ),
|
134 |
+
esc_html( get_class( $alert_type ) )
|
135 |
+
)
|
136 |
+
);
|
137 |
+
}
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Load alert_type classes
|
143 |
+
*
|
144 |
+
* @return void
|
145 |
+
*/
|
146 |
+
function load_alert_triggers() {
|
147 |
+
$alert_triggers = array(
|
148 |
+
'author',
|
149 |
+
'context',
|
150 |
+
'action',
|
151 |
+
);
|
152 |
+
|
153 |
+
$classes = array();
|
154 |
+
foreach ( $alert_triggers as $alert_trigger ) {
|
155 |
+
$file_location = $this->plugin->locations['dir'] . '/alerts/class-alert-trigger-' . $alert_trigger . '.php';
|
156 |
+
if ( file_exists( $file_location ) ) {
|
157 |
+
include_once $file_location;
|
158 |
+
$class_name = sprintf( '\WP_Stream\Alert_Trigger_%s', str_replace( '-', '_', $alert_trigger ) );
|
159 |
+
if ( ! class_exists( $class_name ) ) {
|
160 |
+
continue;
|
161 |
+
}
|
162 |
+
$class = new $class_name( $this->plugin );
|
163 |
+
if ( ! property_exists( $class, 'slug' ) ) {
|
164 |
+
continue;
|
165 |
+
}
|
166 |
+
$classes[ $class->slug ] = $class;
|
167 |
+
}
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Allows for adding additional alert_triggers via classes that extend Notifier.
|
172 |
+
*
|
173 |
+
* @param array $classes An array of Notifier objects. In the format alert_trigger_slug => Notifier_Class()
|
174 |
+
*/
|
175 |
+
$this->alert_triggers = apply_filters( 'wp_stream_alert_triggers', $classes );
|
176 |
+
|
177 |
+
// Ensure that all alert_triggers extend Notifier.
|
178 |
+
foreach ( $this->alert_triggers as $key => $alert_trigger ) {
|
179 |
+
if ( ! $this->is_valid_alert_trigger( $alert_trigger ) ) {
|
180 |
+
unset( $this->alert_triggers[ $key ] );
|
181 |
+
trigger_error(
|
182 |
+
sprintf(
|
183 |
+
esc_html__( 'Registered alert_trigger %s does not extend WP_Stream\Alert_Trigger.', 'stream' ),
|
184 |
+
esc_html( get_class( $alert_trigger ) )
|
185 |
+
)
|
186 |
+
);
|
187 |
+
}
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Checks whether a Alert Type class is valid
|
193 |
+
*
|
194 |
+
* @param Alert_Type $alert_type The class to check.
|
195 |
+
*
|
196 |
+
* @return bool
|
197 |
+
*/
|
198 |
+
public function is_valid_alert_type( $alert_type ) {
|
199 |
+
if ( ! is_a( $alert_type, 'WP_Stream\Alert_Type' ) ) {
|
200 |
+
return false;
|
201 |
+
}
|
202 |
+
|
203 |
+
if ( ! method_exists( $alert_type, 'is_dependency_satisfied' ) || ! $alert_type->is_dependency_satisfied() ) {
|
204 |
+
return false;
|
205 |
+
}
|
206 |
+
|
207 |
+
return true;
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Checks whether a Alert Trigger class is valid
|
212 |
+
*
|
213 |
+
* @param Alert_Trigger $alert_trigger The class to check.
|
214 |
+
*
|
215 |
+
* @return bool
|
216 |
+
*/
|
217 |
+
public function is_valid_alert_trigger( $alert_trigger ) {
|
218 |
+
if ( ! is_a( $alert_trigger, 'WP_Stream\Alert_Trigger' ) ) {
|
219 |
+
return false;
|
220 |
+
}
|
221 |
+
|
222 |
+
if ( ! method_exists( $alert_trigger, 'is_dependency_satisfied' ) || ! $alert_trigger->is_dependency_satisfied() ) {
|
223 |
+
return false;
|
224 |
+
}
|
225 |
+
|
226 |
+
return true;
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Checks record being processed against active alerts.
|
231 |
+
*
|
232 |
+
* @filter wp_stream_record_inserted
|
233 |
+
*
|
234 |
+
* @param int $record_id The record being processed.
|
235 |
+
* @param array $recordarr Record data.
|
236 |
+
*
|
237 |
+
* @return array
|
238 |
+
*/
|
239 |
+
function check_records( $record_id, $recordarr ) {
|
240 |
+
$args = array(
|
241 |
+
'post_type' => self::POST_TYPE,
|
242 |
+
'post_status' => 'wp_stream_enabled',
|
243 |
+
);
|
244 |
+
|
245 |
+
$alerts = new \WP_Query( $args );
|
246 |
+
foreach ( $alerts->posts as $alert ) {
|
247 |
+
$alert = $this->get_alert( $alert->ID );
|
248 |
+
|
249 |
+
$status = $alert->check_record( $record_id, $recordarr );
|
250 |
+
if ( $status ) {
|
251 |
+
$alert->send_alert( $record_id, $recordarr ); // @todo send_alert expects int, not array.
|
252 |
+
}
|
253 |
+
}
|
254 |
+
|
255 |
+
return $recordarr;
|
256 |
+
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Register scripts for page load
|
261 |
+
*
|
262 |
+
* @action admin_enqueue_scripts
|
263 |
+
*
|
264 |
+
* @return void
|
265 |
+
*/
|
266 |
+
function register_scripts() {
|
267 |
+
$screen = get_current_screen();
|
268 |
+
if ( 'edit-wp_stream_alerts' === $screen->id ) {
|
269 |
+
wp_register_script( 'wp-stream-alerts', $this->plugin->locations['url'] . 'ui/js/alerts.js', array(
|
270 |
+
'wp-stream-select2',
|
271 |
+
'jquery',
|
272 |
+
'inline-edit-post',
|
273 |
+
) );
|
274 |
+
wp_localize_script( 'wp-stream-alerts', 'streamAlerts',
|
275 |
+
array(
|
276 |
+
'any' => __( 'Any', 'stream' ),
|
277 |
+
'anyContext' => __( 'Any Context', 'stream' ),
|
278 |
+
)
|
279 |
+
);
|
280 |
+
wp_enqueue_script( 'wp-stream-alerts' );
|
281 |
+
wp_enqueue_style( 'wp-stream-select2' );
|
282 |
+
}
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Register custom post type
|
287 |
+
*
|
288 |
+
* @action init
|
289 |
+
*
|
290 |
+
* @return void
|
291 |
+
*/
|
292 |
+
public function register_post_type() {
|
293 |
+
$labels = array(
|
294 |
+
'name' => _x( 'Alerts', 'post type general name', 'stream' ),
|
295 |
+
'singular_name' => _x( 'Alert', 'post type singular name', 'stream' ),
|
296 |
+
'menu_name' => _x( 'Alerts', 'admin menu', 'stream' ),
|
297 |
+
'name_admin_bar' => _x( 'Alert', 'add new on admin bar', 'stream' ),
|
298 |
+
'add_new' => _x( 'Add New', 'book', 'stream' ),
|
299 |
+
'add_new_item' => __( 'Add New Alert', 'stream' ),
|
300 |
+
'new_item' => __( 'New Alert', 'stream' ),
|
301 |
+
'edit_item' => __( 'Edit Alert', 'stream' ),
|
302 |
+
'view_item' => __( 'View Alert', 'stream' ),
|
303 |
+
'all_items' => __( 'Alerts', 'stream' ),
|
304 |
+
'search_items' => __( 'Search Alerts', 'stream' ),
|
305 |
+
'parent_item_colon' => __( 'Parent Alerts:', 'stream' ),
|
306 |
+
'not_found' => __( 'No alerts found.', 'stream' ),
|
307 |
+
'not_found_in_trash' => __( 'No alerts found in Trash.', 'stream' ),
|
308 |
+
);
|
309 |
+
|
310 |
+
$args = array(
|
311 |
+
'labels' => $labels,
|
312 |
+
'description' => __( 'Alerts for Stream.', 'stream' ),
|
313 |
+
'public' => false,
|
314 |
+
'publicly_queryable' => false,
|
315 |
+
'exclude_from_search' => true,
|
316 |
+
'show_ui' => true,
|
317 |
+
'show_in_menu' => false, // @see modify_admin_menu
|
318 |
+
'supports' => false,
|
319 |
+
'capabilities' => array(
|
320 |
+
'publish_posts' => 'manage_options',
|
321 |
+
'edit_others_posts' => 'manage_options',
|
322 |
+
'delete_posts' => 'manage_options',
|
323 |
+
'delete_others_posts' => 'manage_options',
|
324 |
+
'read_private_posts' => 'manage_options',
|
325 |
+
'edit_post' => 'manage_options',
|
326 |
+
'delete_post' => 'manage_options',
|
327 |
+
'read_post' => 'manage_options',
|
328 |
+
),
|
329 |
+
);
|
330 |
+
|
331 |
+
register_post_type( self::POST_TYPE, $args );
|
332 |
+
|
333 |
+
$args = array(
|
334 |
+
'label' => _x( 'Enabled', 'alert', 'stream' ),
|
335 |
+
'public' => false,
|
336 |
+
'show_in_admin_all_list' => true,
|
337 |
+
'show_in_admin_status_list' => true,
|
338 |
+
'label_count' => _n_noop( 'Enabled <span class="count">(%s)</span>', 'Enabled <span class="count">(%s)</span>', 'stream' ),
|
339 |
+
);
|
340 |
+
|
341 |
+
register_post_status( 'wp_stream_enabled', $args );
|
342 |
+
|
343 |
+
$args = array(
|
344 |
+
'label' => _x( 'Disabled', 'alert', 'stream' ),
|
345 |
+
'public' => false,
|
346 |
+
'internal' => false,
|
347 |
+
'show_in_admin_all_list' => true,
|
348 |
+
'show_in_admin_status_list' => true,
|
349 |
+
'label_count' => _n_noop( 'Disabled <span class="count">(%s)</span>', 'Disabled <span class="count">(%s)</span>', 'stream' ),
|
350 |
+
);
|
351 |
+
|
352 |
+
register_post_status( 'wp_stream_disabled', $args );
|
353 |
+
}
|
354 |
+
|
355 |
+
/**
|
356 |
+
* Return alert object of the given ID
|
357 |
+
*
|
358 |
+
* @param string $post_id Post ID for the alert.
|
359 |
+
*
|
360 |
+
* @return Alert
|
361 |
+
*/
|
362 |
+
public function get_alert( $post_id = '' ) {
|
363 |
+
if ( ! $post_id ) {
|
364 |
+
$obj = new Alert( null, $this->plugin );
|
365 |
+
return $obj;
|
366 |
+
}
|
367 |
+
|
368 |
+
$post = get_post( $post_id );
|
369 |
+
$meta = get_post_custom( $post_id );
|
370 |
+
|
371 |
+
$obj = (object) array(
|
372 |
+
'ID' => $post->ID,
|
373 |
+
'status' => $post->post_status,
|
374 |
+
'date' => $post->post_date,
|
375 |
+
'author' => $post->post_author,
|
376 |
+
'filter_action' => isset( $meta['filter_action'] ) ? $meta['filter_action'][0] : null,
|
377 |
+
'filter_author' => isset( $meta['filter_author'] ) ? $meta['filter_author'][0] : null,
|
378 |
+
'filter_context' => isset( $meta['filter_context'] ) ? $meta['filter_context'][0] : null,
|
379 |
+
'alert_type' => isset( $meta['alert_type'] ) ? $meta['alert_type'][0] : null,
|
380 |
+
'alert_meta' => isset( $meta['alert_meta'] ) ? (array) maybe_unserialize( $meta['alert_meta'][0] ) : array(),
|
381 |
+
);
|
382 |
+
|
383 |
+
return new Alert( $obj, $this->plugin );
|
384 |
+
|
385 |
+
}
|
386 |
+
|
387 |
+
/**
|
388 |
+
* Add custom post type to menu
|
389 |
+
*
|
390 |
+
* @action admin_menu
|
391 |
+
*
|
392 |
+
* @return void
|
393 |
+
*/
|
394 |
+
function register_menu() {
|
395 |
+
add_submenu_page(
|
396 |
+
$this->plugin->admin->records_page_slug,
|
397 |
+
__( 'Alerts', 'stream' ),
|
398 |
+
__( 'Alerts', 'stream' ),
|
399 |
+
'manage_options',
|
400 |
+
'edit.php?post_type=wp_stream_alerts'
|
401 |
+
);
|
402 |
+
}
|
403 |
+
|
404 |
+
/**
|
405 |
+
* Modify the Stream > Alerts Network Admin Menu link.
|
406 |
+
*
|
407 |
+
* In self::register_menu(), the Alerts submenu item
|
408 |
+
* is essentially set to go to the Site's admin area.
|
409 |
+
*
|
410 |
+
* However, on the Network admin, we need to redirect
|
411 |
+
* it to the first site in the network, as this is
|
412 |
+
* where the true Network Alerts settings page is located.
|
413 |
+
*
|
414 |
+
* @action network_admin_menu
|
415 |
+
* @return bool
|
416 |
+
*/
|
417 |
+
function change_menu_link_url() {
|
418 |
+
global $submenu;
|
419 |
+
|
420 |
+
$parent = 'wp_stream';
|
421 |
+
$page = 'edit.php?post_type=wp_stream_alerts';
|
422 |
+
|
423 |
+
// If we're not on the Stream menu item, return.
|
424 |
+
if ( ! isset( $submenu[ $parent ] ) ) {
|
425 |
+
return false;
|
426 |
+
}
|
427 |
+
|
428 |
+
// Get the first existing Site in the Network.
|
429 |
+
// @todo: Switch to use wp_stream_get_sites()
|
430 |
+
$sites = wp_get_sites(
|
431 |
+
array(
|
432 |
+
'limit' => 5, // Limit the size of the query.
|
433 |
+
)
|
434 |
+
);
|
435 |
+
|
436 |
+
$site_id = '1';
|
437 |
+
|
438 |
+
// Function wp_get_sites() can return an empty array if the network is too large.
|
439 |
+
if ( ! empty( $sites ) && ! empty( $sites[0]['blog_id'] ) ) {
|
440 |
+
$site_id = $sites[0]['blog_id'];
|
441 |
+
}
|
442 |
+
|
443 |
+
$new_url = get_admin_url( $site_id, $page );
|
444 |
+
|
445 |
+
foreach ( $submenu[ $parent ] as $key => $value ) {
|
446 |
+
|
447 |
+
// Set correct URL for the menu item.
|
448 |
+
if ( $page === $value[2] ) {
|
449 |
+
$submenu[ $parent ][ $key ][2] = $new_url;
|
450 |
+
break;
|
451 |
+
}
|
452 |
+
}
|
453 |
+
|
454 |
+
return true;
|
455 |
+
}
|
456 |
+
|
457 |
+
/**
|
458 |
+
* Display Alert Type Meta Box
|
459 |
+
*
|
460 |
+
* @param \WP_Post|array $post Post object for current alert.
|
461 |
+
*
|
462 |
+
* @return void
|
463 |
+
*/
|
464 |
+
function display_notification_box( $post = array() ) {
|
465 |
+
$alert_type = 'none';
|
466 |
+
if ( is_object( $post ) ) {
|
467 |
+
$alert = $this->get_alert( $post->ID );
|
468 |
+
$alert_type = $alert->alert_type;
|
469 |
+
}
|
470 |
+
$form = new Form_Generator;
|
471 |
+
|
472 |
+
$field_html = $form->render_field( 'select', array(
|
473 |
+
'id' => 'wp_stream_alert_type',
|
474 |
+
'name' => 'wp_stream_alert_type',
|
475 |
+
'value' => $alert_type,
|
476 |
+
'options' => $this->get_notification_values(),
|
477 |
+
'placeholder' => __( 'No Alert', 'stream' ),
|
478 |
+
'title' => 'Alert Type:',
|
479 |
+
) );
|
480 |
+
|
481 |
+
echo '<label>' . esc_html__( 'Alert me by', 'stream' ) . '</label>';
|
482 |
+
echo $field_html; // Xss ok.
|
483 |
+
|
484 |
+
echo '<div id="wp_stream_alert_type_form">';
|
485 |
+
if ( is_object( $alert ) ) {
|
486 |
+
$alert->get_alert_type_obj()->display_fields( $alert );
|
487 |
+
} else {
|
488 |
+
$this->plugin->alerts->alert_types['none']->display_fields( array() );
|
489 |
+
}
|
490 |
+
|
491 |
+
echo '</div>';
|
492 |
+
}
|
493 |
+
|
494 |
+
/**
|
495 |
+
* Returns settings form HTML for AJAX use
|
496 |
+
*
|
497 |
+
* @action wp_ajax_load_alerts_settings
|
498 |
+
*
|
499 |
+
* @return void
|
500 |
+
*/
|
501 |
+
function load_alerts_settings() {
|
502 |
+
$alert = array();
|
503 |
+
$post_id = wp_stream_filter_input( INPUT_POST, 'post_id' );
|
504 |
+
if ( ! empty( $post_id ) ) {
|
505 |
+
$alert = $this->get_alert( $post_id );
|
506 |
+
if ( ! $alert ) {
|
507 |
+
wp_send_json_error( array(
|
508 |
+
'message' => 'Could not find alert.',
|
509 |
+
) );
|
510 |
+
}
|
511 |
+
}
|
512 |
+
|
513 |
+
$alert_type = wp_stream_filter_input( INPUT_POST, 'alert_type' );
|
514 |
+
if ( empty( $alert_type ) ) {
|
515 |
+
$alert_type = 'none';
|
516 |
+
}
|
517 |
+
if ( ! array_key_exists( $alert_type, $this->alert_types ) ) {
|
518 |
+
wp_send_json_error( array(
|
519 |
+
'message' => 'Could not find alert type.',
|
520 |
+
) );
|
521 |
+
}
|
522 |
+
|
523 |
+
ob_start();
|
524 |
+
$this->alert_types[ $alert_type ]->display_fields( $alert );
|
525 |
+
$output = ob_get_contents();
|
526 |
+
ob_end_clean();
|
527 |
+
|
528 |
+
$data = array( 'html' => $output );
|
529 |
+
wp_send_json_success( $data );
|
530 |
+
}
|
531 |
+
|
532 |
+
/**
|
533 |
+
* Display Trigger Meta Box
|
534 |
+
*
|
535 |
+
* @param \WP_Post|array $post Post object for current alert.
|
536 |
+
*
|
537 |
+
* @return void
|
538 |
+
*/
|
539 |
+
function display_triggers_box( $post = array() ) {
|
540 |
+
if ( is_object( $post ) ) {
|
541 |
+
$alert = $this->get_alert( $post->ID );
|
542 |
+
} else {
|
543 |
+
$alert = array();
|
544 |
+
}
|
545 |
+
$form = new Form_Generator;
|
546 |
+
do_action( 'wp_stream_alert_trigger_form_display', $form, $alert );
|
547 |
+
// @TODO use human readable text.
|
548 |
+
echo '<label>' . esc_html__( 'Alert me when', 'stream' ) . '</label>';
|
549 |
+
echo $form->render_fields(); // Xss ok.
|
550 |
+
wp_nonce_field( 'save_alert', 'wp_stream_alerts_nonce' );
|
551 |
+
}
|
552 |
+
|
553 |
+
/**
|
554 |
+
* Display Submit Box
|
555 |
+
*
|
556 |
+
* @param \WP_Post $post Post object for current alert.
|
557 |
+
*
|
558 |
+
* @return void
|
559 |
+
*/
|
560 |
+
function display_submit_box( $post ) {
|
561 |
+
if ( empty( $post ) ) {
|
562 |
+
return;
|
563 |
+
}
|
564 |
+
|
565 |
+
$post_status = $post->post_status;
|
566 |
+
if ( 'auto-draft' === $post_status ) {
|
567 |
+
$post_status = 'wp_stream_enabled';
|
568 |
+
}
|
569 |
+
?>
|
570 |
+
<div class="submitbox" id="submitpost">
|
571 |
+
<div id="minor-publishing">
|
572 |
+
<div id="misc-publishing-actions">
|
573 |
+
<div class="misc-pub-section misc-pub-post-status">
|
574 |
+
<label for="wp_stream_alert_status"><?php esc_html_e( 'Status', 'stream' ) ?></label>
|
575 |
+
<select name='wp_stream_alert_status' id='wp_stream_alert_status'>
|
576 |
+
<option<?php selected( $post_status, 'wp_stream_enabled' ); ?>
|
577 |
+
value='wp_stream_enabled'><?php esc_html_e( 'Enabled', 'stream' ) ?></option>
|
578 |
+
<option<?php selected( $post_status, 'wp_stream_disabled' ); ?>
|
579 |
+
value='wp_stream_disabled'><?php esc_html_e( 'Disabled', 'stream' ) ?></option>
|
580 |
+
</select>
|
581 |
+
</div>
|
582 |
+
</div>
|
583 |
+
<div class="clear"></div>
|
584 |
+
</div>
|
585 |
+
|
586 |
+
<div id="major-publishing-actions">
|
587 |
+
<div id="delete-action">
|
588 |
+
<?php
|
589 |
+
if ( current_user_can( 'delete_post', $post->ID ) ) {
|
590 |
+
if ( ! EMPTY_TRASH_DAYS ) {
|
591 |
+
$delete_text = __( 'Delete Permanently', 'stream' );
|
592 |
+
} else {
|
593 |
+
$delete_text = __( 'Move to Trash', 'stream' );
|
594 |
+
}
|
595 |
+
?>
|
596 |
+
<a class="submitdelete deletion"
|
597 |
+
href="<?php echo get_delete_post_link( $post->ID ); ?>"><?php esc_html( $delete_text ); ?></a><?php
|
598 |
+
} ?>
|
599 |
+
</div>
|
600 |
+
<div id="publishing-action">
|
601 |
+
<span class="spinner"></span>
|
602 |
+
<?php submit_button( __( 'Save' ), 'primary button-large', 'publish', false ); ?>
|
603 |
+
</div>
|
604 |
+
<div class="clear"></div>
|
605 |
+
</div>
|
606 |
+
</div>
|
607 |
+
<?php
|
608 |
+
}
|
609 |
+
|
610 |
+
/**
|
611 |
+
* Display Status Box
|
612 |
+
*
|
613 |
+
* @return void
|
614 |
+
*/
|
615 |
+
function display_status_box() {
|
616 |
+
?>
|
617 |
+
<div id="minor-publishing">
|
618 |
+
<div id="misc-publishing-actions">
|
619 |
+
<div class="misc-pub-section misc-pub-post-status">
|
620 |
+
<label for="wp_stream_alert_status">
|
621 |
+
<span class="title"><?php esc_html_e( 'Status:', 'stream' ) ?></span>
|
622 |
+
<span class="input-text-wrap">
|
623 |
+
<select name='wp_stream_alert_status' id='wp_stream_alert_status'>
|
624 |
+
<option selected value='wp_stream_enabled'><?php esc_html_e( 'Enabled', 'stream' ) ?></option>
|
625 |
+
<option value='wp_stream_disabled'><?php esc_html_e( 'Disabled', 'stream' ) ?></option>
|
626 |
+
</select>
|
627 |
+
</span>
|
628 |
+
</label>
|
629 |
+
</div>
|
630 |
+
</div>
|
631 |
+
<div class="clear"></div>
|
632 |
+
</div>
|
633 |
+
<?php
|
634 |
+
}
|
635 |
+
|
636 |
+
/**
|
637 |
+
* Return all notification values
|
638 |
+
*
|
639 |
+
* @return array
|
640 |
+
*/
|
641 |
+
function get_notification_values() {
|
642 |
+
$result = array();
|
643 |
+
$names = wp_list_pluck( $this->alert_types, 'name', 'slug' );
|
644 |
+
foreach ( $names as $slug => $name ) {
|
645 |
+
$result[ $slug ] = $name;
|
646 |
+
}
|
647 |
+
|
648 |
+
return $result;
|
649 |
+
}
|
650 |
+
|
651 |
+
/**
|
652 |
+
* Update actions dropdown options based on the connector selected.
|
653 |
+
*/
|
654 |
+
function get_actions() {
|
655 |
+
$connector_name = wp_stream_filter_input( INPUT_POST, 'connector' );
|
656 |
+
$stream_connectors = wp_stream_get_instance()->connectors;
|
657 |
+
if ( ! empty( $connector_name ) ) {
|
658 |
+
if ( isset( $stream_connectors->connectors[ $connector_name ] ) ) {
|
659 |
+
$connector = $stream_connectors->connectors[ $connector_name ];
|
660 |
+
if ( method_exists( $connector, 'get_action_labels' ) ) {
|
661 |
+
$actions = $connector->get_action_labels();
|
662 |
+
}
|
663 |
+
}
|
664 |
+
} else {
|
665 |
+
$actions = $stream_connectors->term_labels['stream_action'];
|
666 |
+
}
|
667 |
+
ksort( $actions );
|
668 |
+
wp_send_json_success( $actions );
|
669 |
+
}
|
670 |
+
|
671 |
+
/**
|
672 |
+
* Save a new alert
|
673 |
+
*/
|
674 |
+
function save_new_alert() {
|
675 |
+
check_ajax_referer( 'save_alert', 'wp_stream_alerts_nonce' );
|
676 |
+
$trigger_author = wp_stream_filter_input( INPUT_POST, 'wp_stream_trigger_author' );
|
677 |
+
$trigger_connector_and_context = wp_stream_filter_input( INPUT_POST, 'wp_stream_trigger_context' );
|
678 |
+
if ( false !== strpos( $trigger_connector_and_context, '-' ) ) {
|
679 |
+
// This is a connector with a context such as posts-post.
|
680 |
+
$trigger_connector_and_context_split = explode( '-', $trigger_connector_and_context );
|
681 |
+
$trigger_connector = $trigger_connector_and_context_split[0];
|
682 |
+
$trigger_context = $trigger_connector_and_context_split[1];
|
683 |
+
} else {
|
684 |
+
if ( ! empty( $trigger_connector_and_context ) ) {
|
685 |
+
// This is a parent connector with no dash such as posts.
|
686 |
+
$trigger_connector = $trigger_connector_and_context;
|
687 |
+
$trigger_context = '';
|
688 |
+
} else {
|
689 |
+
// There is no connector or context.
|
690 |
+
$trigger_connector = '';
|
691 |
+
$trigger_context = '';
|
692 |
+
}
|
693 |
+
}
|
694 |
+
|
695 |
+
$trigger_action = wp_stream_filter_input( INPUT_POST, 'wp_stream_trigger_action' );
|
696 |
+
$alert_type = wp_stream_filter_input( INPUT_POST, 'wp_stream_alert_type' );
|
697 |
+
$alert_status = wp_stream_filter_input( INPUT_POST, 'wp_stream_alert_status' );
|
698 |
+
|
699 |
+
// Insert the post into the database
|
700 |
+
$item = (object) array(
|
701 |
+
'alert_type' => $alert_type,
|
702 |
+
'alert_meta' => array(
|
703 |
+
'trigger_author' => $trigger_author,
|
704 |
+
'trigger_connector' => $trigger_connector,
|
705 |
+
'trigger_action' => $trigger_action,
|
706 |
+
'trigger_context' => $trigger_context,
|
707 |
+
),
|
708 |
+
'alert_status' => $alert_status,
|
709 |
+
);
|
710 |
+
$alert = new Alert( $item, $this->plugin );
|
711 |
+
$title = $alert->get_title();
|
712 |
+
$post_id = wp_insert_post( array(
|
713 |
+
'post_status' => $alert_status,
|
714 |
+
'post_type' => 'wp_stream_alerts',
|
715 |
+
'post_title' => $title,
|
716 |
+
) );
|
717 |
+
if ( empty( $post_id ) ) {
|
718 |
+
wp_send_json_error();
|
719 |
+
}
|
720 |
+
add_post_meta( $post_id, 'alert_type', $alert_type );
|
721 |
+
|
722 |
+
$alert_meta = array(
|
723 |
+
'trigger_author' => $trigger_author,
|
724 |
+
'trigger_connector' => $trigger_connector,
|
725 |
+
'trigger_action' => $trigger_action,
|
726 |
+
'trigger_context' => $trigger_context,
|
727 |
+
);
|
728 |
+
$alert_meta = apply_filters( 'wp_stream_alerts_save_meta', $alert_meta, $alert_type );
|
729 |
+
add_post_meta( $post_id, 'alert_meta', $alert_meta );
|
730 |
+
wp_send_json_success( array( 'success' => true ) );
|
731 |
+
}
|
732 |
+
|
733 |
+
/**
|
734 |
+
*
|
735 |
+
*/
|
736 |
+
function get_new_alert_triggers_notifications() {
|
737 |
+
ob_start();
|
738 |
+
?>
|
739 |
+
<fieldset class="inline-edit-col inline-edit-wp_stream_alerts inline-edit-add-new-triggers">
|
740 |
+
<legend class="inline-edit-legend">Add New</legend>
|
741 |
+
<?php $GLOBALS['wp_stream']->alerts->display_triggers_box(); ?>
|
742 |
+
</fieldset>
|
743 |
+
<fieldset class="inline-edit-col inline-edit-wp_stream_alerts inline-edit-add-new-notifications">
|
744 |
+
<?php $GLOBALS['wp_stream']->alerts->display_notification_box(); ?>
|
745 |
+
</fieldset>
|
746 |
+
<fieldset class="inline-edit-col inline-edit-wp_stream_alerts inline-edit-add-new-status">
|
747 |
+
<?php $GLOBALS['wp_stream']->alerts->display_status_box(); ?>
|
748 |
+
</fieldset>
|
749 |
+
<?php
|
750 |
+
$html = ob_get_clean();
|
751 |
+
wp_send_json_success( array( 'success' => true, 'html' => $html ) );
|
752 |
+
}
|
753 |
+
/**
|
754 |
+
* Add action links to Stream drop row in admin list screen
|
755 |
+
*
|
756 |
+
* @filter wp_stream_action_links_{connector}
|
757 |
+
*
|
758 |
+
* @param array $links Previous links registered
|
759 |
+
* @param Record $record Stream record
|
760 |
+
*
|
761 |
+
* @return array Action links
|
762 |
+
*/
|
763 |
+
function change_alert_action_links( $links, $record ) {
|
764 |
+
$post = get_post( $record->object_id );
|
765 |
+
|
766 |
+
if ( $post && self::POST_TYPE === $post->post_type && $post->post_status === $record->get_meta( 'new_status', true ) ) {
|
767 |
+
if ( 'trash' !== $post->post_status ) {
|
768 |
+
$connector_posts = new \WP_Stream\Connector_Posts;
|
769 |
+
$post_type_name = $connector_posts->get_post_type_name( get_post_type( $post->ID ) );
|
770 |
+
|
771 |
+
$links[ sprintf( esc_html_x( 'Edit %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = admin_url( 'edit.php?post_type=wp_stream_alerts#post-' . $post->ID );
|
772 |
+
unset( $links[ esc_html__( 'View', 'stream' ) ] );
|
773 |
+
}
|
774 |
+
}
|
775 |
+
return $links;
|
776 |
+
}
|
777 |
+
}
|
classes/class-connectors.php
CHANGED
@@ -93,7 +93,7 @@ class Connectors {
|
|
93 |
continue;
|
94 |
}
|
95 |
if ( $class->is_dependency_satisfied() ) {
|
96 |
-
$classes[] = $class;
|
97 |
}
|
98 |
}
|
99 |
|
@@ -120,25 +120,25 @@ class Connectors {
|
|
120 |
|
121 |
foreach ( $this->connectors as $connector ) {
|
122 |
if ( ! method_exists( $connector, 'get_label' ) ) {
|
123 |
-
$this->plugin->admin->notice( sprintf( __(
|
124 |
continue;
|
125 |
}
|
126 |
if ( ! method_exists( $connector, 'register' ) ) {
|
127 |
-
$this->plugin->admin->notice( sprintf( __(
|
128 |
continue;
|
129 |
}
|
130 |
if ( ! method_exists( $connector, 'get_context_labels' ) ) {
|
131 |
-
$this->plugin->admin->notice( sprintf( __(
|
132 |
continue;
|
133 |
}
|
134 |
if ( ! method_exists( $connector, 'get_action_labels' ) ) {
|
135 |
-
$this->plugin->admin->notice( sprintf( __(
|
136 |
continue;
|
137 |
}
|
138 |
|
139 |
-
// Check if the connectors extends the Connector class, if not skip it
|
140 |
if ( ! is_subclass_of( $connector, '\WP_Stream\Connector' ) ) {
|
141 |
-
$this->plugin->admin->notice( sprintf( __(
|
142 |
continue;
|
143 |
}
|
144 |
|
93 |
continue;
|
94 |
}
|
95 |
if ( $class->is_dependency_satisfied() ) {
|
96 |
+
$classes[ $class->name ] = $class;
|
97 |
}
|
98 |
}
|
99 |
|
120 |
|
121 |
foreach ( $this->connectors as $connector ) {
|
122 |
if ( ! method_exists( $connector, 'get_label' ) ) {
|
123 |
+
$this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the get_label method.', 'stream' ), $connector->name, 'Connector' ), true );
|
124 |
continue;
|
125 |
}
|
126 |
if ( ! method_exists( $connector, 'register' ) ) {
|
127 |
+
$this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the register method.', 'stream' ), $connector->name, 'Connector' ), true );
|
128 |
continue;
|
129 |
}
|
130 |
if ( ! method_exists( $connector, 'get_context_labels' ) ) {
|
131 |
+
$this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the get_context_labels method.', 'stream' ), $connector->name, 'Connector' ), true );
|
132 |
continue;
|
133 |
}
|
134 |
if ( ! method_exists( $connector, 'get_action_labels' ) ) {
|
135 |
+
$this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the get_action_labels method.', 'stream' ), $connector->name, 'Connector' ), true );
|
136 |
continue;
|
137 |
}
|
138 |
|
139 |
+
// Check if the connectors extends the Connector class, if not skip it.
|
140 |
if ( ! is_subclass_of( $connector, '\WP_Stream\Connector' ) ) {
|
141 |
+
$this->plugin->admin->notice( sprintf( __( '%1$s class wasn\'t loaded because it doesn\'t extends the %2$s class.', 'stream' ), $connector->name, 'Connector' ), true );
|
142 |
continue;
|
143 |
}
|
144 |
|
classes/class-form-generator.php
CHANGED
@@ -116,7 +116,7 @@ class Form_Generator {
|
|
116 |
|
117 |
$multiple = ( $args['multiple'] ) ? 'multiple ' : '';
|
118 |
$output = sprintf(
|
119 |
-
'<select name="%1$s" id="%1$s" class="select2-select %2$s" %3$s%4$s
|
120 |
esc_attr( $args['name'] ),
|
121 |
esc_attr( $args['classes'] ),
|
122 |
$this->prepare_data_attributes_string( $args['data'] ),
|
@@ -133,36 +133,38 @@ class Form_Generator {
|
|
133 |
'text' => '',
|
134 |
'children' => array(),
|
135 |
) );
|
|
|
|
|
|
|
136 |
if ( is_array( $args['value'] ) ) {
|
137 |
-
$selected = selected( in_array( $parent['
|
138 |
} else {
|
139 |
-
$selected = selected( $args['value'], $parent['
|
140 |
}
|
141 |
$output .= sprintf(
|
142 |
'<option class="parent" value="%1$s" %3$s>%2$s</option>',
|
143 |
-
$parent['
|
144 |
$parent['text'],
|
145 |
$selected
|
146 |
);
|
147 |
-
$values[] = $parent['
|
148 |
if ( ! empty( $parent['children'] ) ) {
|
149 |
foreach ( $parent['children'] as $child ) {
|
150 |
$output .= sprintf(
|
151 |
'<option class="child" value="%1$s" %3$s>%2$s</option>',
|
152 |
-
$child['
|
153 |
$child['text'],
|
154 |
-
selected( $args['value'], $child['
|
155 |
);
|
156 |
-
$values[] = $child['
|
157 |
}
|
158 |
$output .= '</optgroup>';
|
159 |
}
|
160 |
}
|
161 |
|
162 |
$selected_values = explode( ',', $args['value'] );
|
163 |
-
|
164 |
foreach ( $selected_values as $selected_value ) {
|
165 |
-
if ( ! empty( $selected_value ) && ! in_array( $selected_value, $values, true ) ) {
|
166 |
$output .= sprintf(
|
167 |
'<option value="%1$s" %2$s>%1$s</option>',
|
168 |
$selected_value,
|
@@ -194,7 +196,7 @@ class Form_Generator {
|
|
194 |
/**
|
195 |
* Prepares string with HTML data attributes
|
196 |
*
|
197 |
-
* @param $data
|
198 |
* @return string
|
199 |
*/
|
200 |
public function prepare_data_attributes_string( $data ) {
|
116 |
|
117 |
$multiple = ( $args['multiple'] ) ? 'multiple ' : '';
|
118 |
$output = sprintf(
|
119 |
+
'<select name="%1$s" id="%1$s" class="select2-select %2$s" %3$s%4$s>',
|
120 |
esc_attr( $args['name'] ),
|
121 |
esc_attr( $args['classes'] ),
|
122 |
$this->prepare_data_attributes_string( $args['data'] ),
|
133 |
'text' => '',
|
134 |
'children' => array(),
|
135 |
) );
|
136 |
+
if ( empty( $parent['id'] ) ) {
|
137 |
+
continue;
|
138 |
+
}
|
139 |
if ( is_array( $args['value'] ) ) {
|
140 |
+
$selected = selected( in_array( $parent['id'], $args['value'], true ), true, false );
|
141 |
} else {
|
142 |
+
$selected = selected( $args['value'], $parent['id'], false );
|
143 |
}
|
144 |
$output .= sprintf(
|
145 |
'<option class="parent" value="%1$s" %3$s>%2$s</option>',
|
146 |
+
$parent['id'],
|
147 |
$parent['text'],
|
148 |
$selected
|
149 |
);
|
150 |
+
$values[] = $parent['id'];
|
151 |
if ( ! empty( $parent['children'] ) ) {
|
152 |
foreach ( $parent['children'] as $child ) {
|
153 |
$output .= sprintf(
|
154 |
'<option class="child" value="%1$s" %3$s>%2$s</option>',
|
155 |
+
$child['id'],
|
156 |
$child['text'],
|
157 |
+
selected( $args['value'], $child['id'], false )
|
158 |
);
|
159 |
+
$values[] = $child['id'];
|
160 |
}
|
161 |
$output .= '</optgroup>';
|
162 |
}
|
163 |
}
|
164 |
|
165 |
$selected_values = explode( ',', $args['value'] );
|
|
|
166 |
foreach ( $selected_values as $selected_value ) {
|
167 |
+
if ( ! empty( $selected_value ) && ! in_array( $selected_value, array_map( 'strval', $values ), true ) ) {
|
168 |
$output .= sprintf(
|
169 |
'<option value="%1$s" %2$s>%1$s</option>',
|
170 |
$selected_value,
|
196 |
/**
|
197 |
* Prepares string with HTML data attributes
|
198 |
*
|
199 |
+
* @param array $data List of key/value data pairs to prepare.
|
200 |
* @return string
|
201 |
*/
|
202 |
public function prepare_data_attributes_string( $data ) {
|
classes/class-install.php
CHANGED
@@ -76,8 +76,6 @@ class Install {
|
|
76 |
* @return void
|
77 |
*/
|
78 |
public function check() {
|
79 |
-
global $wpdb;
|
80 |
-
|
81 |
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
82 |
return;
|
83 |
}
|
@@ -97,15 +95,16 @@ class Install {
|
|
97 |
if ( ! $update ) {
|
98 |
$this->update_required = true;
|
99 |
$this->success_db = $this->update( $this->db_version, $this->plugin->get_version(), array( 'type' => 'auto' ) );
|
100 |
-
}
|
|
|
|
|
101 |
$this->success_db = $this->update( $this->db_version, $this->plugin->get_version(), array( 'type' => 'user' ) );
|
102 |
}
|
103 |
|
104 |
$versions = $this->db_update_versions();
|
105 |
|
106 |
-
if ( version_compare( end( $versions ), $this->db_version, '>' ) ) {
|
107 |
add_action( 'all_admin_notices', array( $this, 'update_notice_hook' ) );
|
108 |
-
|
109 |
return;
|
110 |
}
|
111 |
|
@@ -337,6 +336,7 @@ class Install {
|
|
337 |
$db_update_versions = array(
|
338 |
'3.0.0' /* @version 3.0.0 Drop the stream_context table, changes to stream table */,
|
339 |
'3.0.2' /* @version 3.0.2 Fix uppercase values in stream table, connector column */,
|
|
|
340 |
);
|
341 |
|
342 |
/**
|
@@ -399,7 +399,7 @@ class Install {
|
|
399 |
blog_id bigint(20) unsigned NOT NULL DEFAULT '1',
|
400 |
object_id bigint(20) unsigned NULL,
|
401 |
user_id bigint(20) unsigned NOT NULL DEFAULT '0',
|
402 |
-
user_role varchar(
|
403 |
summary longtext NOT NULL,
|
404 |
created datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
405 |
connector varchar(100) NOT NULL,
|
76 |
* @return void
|
77 |
*/
|
78 |
public function check() {
|
|
|
|
|
79 |
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
80 |
return;
|
81 |
}
|
95 |
if ( ! $update ) {
|
96 |
$this->update_required = true;
|
97 |
$this->success_db = $this->update( $this->db_version, $this->plugin->get_version(), array( 'type' => 'auto' ) );
|
98 |
+
}
|
99 |
+
|
100 |
+
if ( 'update_and_continue' === $update ) {
|
101 |
$this->success_db = $this->update( $this->db_version, $this->plugin->get_version(), array( 'type' => 'user' ) );
|
102 |
}
|
103 |
|
104 |
$versions = $this->db_update_versions();
|
105 |
|
106 |
+
if ( ! $this->success_db && version_compare( end( $versions ), $this->db_version, '>' ) ) {
|
107 |
add_action( 'all_admin_notices', array( $this, 'update_notice_hook' ) );
|
|
|
108 |
return;
|
109 |
}
|
110 |
|
336 |
$db_update_versions = array(
|
337 |
'3.0.0' /* @version 3.0.0 Drop the stream_context table, changes to stream table */,
|
338 |
'3.0.2' /* @version 3.0.2 Fix uppercase values in stream table, connector column */,
|
339 |
+
'3.0.8' /* @version 3.0.8 Increase size of user role IDs, user_roll column */,
|
340 |
);
|
341 |
|
342 |
/**
|
399 |
blog_id bigint(20) unsigned NOT NULL DEFAULT '1',
|
400 |
object_id bigint(20) unsigned NULL,
|
401 |
user_id bigint(20) unsigned NOT NULL DEFAULT '0',
|
402 |
+
user_role varchar(50) NOT NULL DEFAULT '',
|
403 |
summary longtext NOT NULL,
|
404 |
created datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
405 |
connector varchar(100) NOT NULL,
|
classes/class-list-table.php
CHANGED
@@ -13,7 +13,7 @@ class List_Table extends \WP_List_Table {
|
|
13 |
* Class constructor.
|
14 |
*
|
15 |
* @param Plugin $plugin The main Plugin class.
|
16 |
-
* @param array
|
17 |
*/
|
18 |
function __construct( $plugin, $args = array() ) {
|
19 |
$this->plugin = $plugin;
|
@@ -308,8 +308,8 @@ class List_Table extends \WP_List_Table {
|
|
308 |
|
309 |
default :
|
310 |
/**
|
311 |
-
* Registers new Columns to be inserted into the table.
|
312 |
-
* below with '
|
313 |
*
|
314 |
* @return array
|
315 |
*/
|
@@ -325,7 +325,7 @@ class List_Table extends \WP_List_Table {
|
|
325 |
* Also, note that the action name must include the $column_title registered
|
326 |
* with wp_stream_register_column_defaults
|
327 |
*/
|
328 |
-
if ( $column_title === $column_name && has_filter( "
|
329 |
/**
|
330 |
* Allows for the addition of content under a specified column.
|
331 |
*
|
@@ -333,7 +333,7 @@ class List_Table extends \WP_List_Table {
|
|
333 |
*
|
334 |
* @return string
|
335 |
*/
|
336 |
-
$out = apply_filters( "
|
337 |
} else {
|
338 |
$out = $column_name;
|
339 |
}
|
@@ -869,6 +869,18 @@ class List_Table extends \WP_List_Table {
|
|
869 |
echo '</form>';
|
870 |
}
|
871 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
872 |
function display_tablenav( $which ) {
|
873 |
if ( 'top' === $which ) : ?>
|
874 |
<div class="tablenav <?php echo esc_attr( $which ); ?>">
|
13 |
* Class constructor.
|
14 |
*
|
15 |
* @param Plugin $plugin The main Plugin class.
|
16 |
+
* @param array $args
|
17 |
*/
|
18 |
function __construct( $plugin, $args = array() ) {
|
19 |
$this->plugin = $plugin;
|
308 |
|
309 |
default :
|
310 |
/**
|
311 |
+
* Registers new Columns to be inserted into the table. The cell contents of this column is set
|
312 |
+
* below with 'wp_stream_insert_column_default_'
|
313 |
*
|
314 |
* @return array
|
315 |
*/
|
325 |
* Also, note that the action name must include the $column_title registered
|
326 |
* with wp_stream_register_column_defaults
|
327 |
*/
|
328 |
+
if ( $column_title === $column_name && has_filter( "wp_stream_insert_column_default_{$column_title}" ) ) {
|
329 |
/**
|
330 |
* Allows for the addition of content under a specified column.
|
331 |
*
|
333 |
*
|
334 |
* @return string
|
335 |
*/
|
336 |
+
$out = apply_filters( "wp_stream_insert_column_default_{$column_title}", $column_name, $record );
|
337 |
} else {
|
338 |
$out = $column_name;
|
339 |
}
|
869 |
echo '</form>';
|
870 |
}
|
871 |
|
872 |
+
function single_row( $item ) {
|
873 |
+
$classes = apply_filters( 'wp_stream_record_classes', array(), $item );
|
874 |
+
$class_string = '';
|
875 |
+
if ( ! empty( $classes ) ) {
|
876 |
+
$class_string = ' class="' . esc_attr( join( ' ', $classes ) ) . '"';
|
877 |
+
}
|
878 |
+
|
879 |
+
echo sprintf( '<tr%s>', $class_string ); // xss ok
|
880 |
+
$this->single_row_columns( $item );
|
881 |
+
echo '</tr>';
|
882 |
+
}
|
883 |
+
|
884 |
function display_tablenav( $which ) {
|
885 |
if ( 'top' === $which ) : ?>
|
886 |
<div class="tablenav <?php echo esc_attr( $which ); ?>">
|
classes/class-live-update.php
CHANGED
@@ -184,7 +184,7 @@ class Live_Update {
|
|
184 |
|
185 |
if ( isset( $data['wp-stream-heartbeat'] ) && isset( $total_items ) ) {
|
186 |
$response['total_items'] = $total_items;
|
187 |
-
$response['total_items_i18n'] = sprintf( _n( '
|
188 |
}
|
189 |
|
190 |
if ( isset( $data['wp-stream-heartbeat'] ) && 'live-update' === $data['wp-stream-heartbeat'] && $enable_stream_update ) {
|
184 |
|
185 |
if ( isset( $data['wp-stream-heartbeat'] ) && isset( $total_items ) ) {
|
186 |
$response['total_items'] = $total_items;
|
187 |
+
$response['total_items_i18n'] = sprintf( _n( '%d item', '%d items', $total_items ), number_format_i18n( $total_items ) );
|
188 |
}
|
189 |
|
190 |
if ( isset( $data['wp-stream-heartbeat'] ) && 'live-update' === $data['wp-stream-heartbeat'] && $enable_stream_update ) {
|
classes/class-network.php
CHANGED
@@ -220,9 +220,11 @@ class Network {
|
|
220 |
'wp_stream_hidden_option_fields',
|
221 |
array(
|
222 |
'general' => array(
|
223 |
-
'delete_all_records',
|
224 |
'records_ttl',
|
225 |
),
|
|
|
|
|
|
|
226 |
)
|
227 |
);
|
228 |
|
@@ -479,7 +481,7 @@ class Network {
|
|
479 |
*/
|
480 |
public function network_admin_page_title( $page_title ) {
|
481 |
if ( is_network_admin() ) {
|
482 |
-
$site_count = sprintf( _n( '
|
483 |
$page_title = sprintf( '%s (%s)', $page_title, $site_count );
|
484 |
}
|
485 |
|
220 |
'wp_stream_hidden_option_fields',
|
221 |
array(
|
222 |
'general' => array(
|
|
|
223 |
'records_ttl',
|
224 |
),
|
225 |
+
'advanced' => array(
|
226 |
+
'delete_all_records',
|
227 |
+
),
|
228 |
)
|
229 |
);
|
230 |
|
481 |
*/
|
482 |
public function network_admin_page_title( $page_title ) {
|
483 |
if ( is_network_admin() ) {
|
484 |
+
$site_count = sprintf( _n( '%d site', '%d sites', get_blog_count(), 'stream' ), number_format( get_blog_count() ) );
|
485 |
$page_title = sprintf( '%s (%s)', $page_title, $site_count );
|
486 |
}
|
487 |
|
classes/class-plugin.php
CHANGED
@@ -7,7 +7,7 @@ class Plugin {
|
|
7 |
*
|
8 |
* @const string
|
9 |
*/
|
10 |
-
const VERSION = '3.
|
11 |
|
12 |
/**
|
13 |
* WP-CLI command
|
@@ -21,6 +21,16 @@ class Plugin {
|
|
21 |
*/
|
22 |
public $admin;
|
23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
/**
|
25 |
* @var Connectors
|
26 |
*/
|
@@ -98,7 +108,7 @@ class Plugin {
|
|
98 |
add_action( 'wp_head', array( $this, 'frontend_indicator' ) );
|
99 |
|
100 |
// Load admin area classes
|
101 |
-
if ( is_admin() || ( defined( 'WP_STREAM_DEV_DEBUG' ) && WP_STREAM_DEV_DEBUG ) ) {
|
102 |
$this->admin = new Admin( $this );
|
103 |
$this->install = new Install( $this );
|
104 |
} elseif ( defined( 'DOING_CRON' ) && DOING_CRON ) {
|
@@ -150,13 +160,16 @@ class Plugin {
|
|
150 |
}
|
151 |
|
152 |
/*
|
153 |
-
* Load Settings and Connectors
|
154 |
*
|
155 |
* @action init
|
156 |
*/
|
157 |
public function init() {
|
158 |
-
$this->settings
|
159 |
-
$this->connectors
|
|
|
|
|
|
|
160 |
}
|
161 |
|
162 |
/**
|
7 |
*
|
8 |
* @const string
|
9 |
*/
|
10 |
+
const VERSION = '3.1';
|
11 |
|
12 |
/**
|
13 |
* WP-CLI command
|
21 |
*/
|
22 |
public $admin;
|
23 |
|
24 |
+
/**
|
25 |
+
* @var Alerts
|
26 |
+
*/
|
27 |
+
public $alerts;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var Alerts_List
|
31 |
+
*/
|
32 |
+
public $alerts_list;
|
33 |
+
|
34 |
/**
|
35 |
* @var Connectors
|
36 |
*/
|
108 |
add_action( 'wp_head', array( $this, 'frontend_indicator' ) );
|
109 |
|
110 |
// Load admin area classes
|
111 |
+
if ( is_admin() || ( defined( 'WP_STREAM_DEV_DEBUG' ) && WP_STREAM_DEV_DEBUG ) || ( defined( 'WP_CLI' ) && WP_CLI ) ) {
|
112 |
$this->admin = new Admin( $this );
|
113 |
$this->install = new Install( $this );
|
114 |
} elseif ( defined( 'DOING_CRON' ) && DOING_CRON ) {
|
160 |
}
|
161 |
|
162 |
/*
|
163 |
+
* Load Settings, Notifications, and Connectors
|
164 |
*
|
165 |
* @action init
|
166 |
*/
|
167 |
public function init() {
|
168 |
+
$this->settings = new Settings( $this );
|
169 |
+
$this->connectors = new Connectors( $this );
|
170 |
+
$this->alerts = new Alerts( $this );
|
171 |
+
$this->alerts_list = new Alerts_List( $this );
|
172 |
+
|
173 |
}
|
174 |
|
175 |
/**
|
classes/class-preview-list-table.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WP_Stream;
|
3 |
+
|
4 |
+
class Preview_List_Table extends List_Table {
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class constructor.
|
8 |
+
*
|
9 |
+
* @param Plugin $plugin Plugin object.
|
10 |
+
* @return void
|
11 |
+
*/
|
12 |
+
public function __construct( $plugin ) {
|
13 |
+
$this->plugin = $plugin;
|
14 |
+
parent::__construct( $plugin );
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Sets up the records for display.
|
19 |
+
*
|
20 |
+
* @param array $items List of items for display.
|
21 |
+
* @return void
|
22 |
+
*/
|
23 |
+
function set_records( $items ) {
|
24 |
+
$columns = $this->get_columns();
|
25 |
+
$sortable = $this->get_sortable_columns();
|
26 |
+
$hidden = $this->get_hidden_columns();
|
27 |
+
$primary = $columns['summary'];
|
28 |
+
|
29 |
+
$this->_column_headers = array( $columns, $hidden, $sortable, $primary );
|
30 |
+
|
31 |
+
$this->items = $items;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Display the table
|
36 |
+
*
|
37 |
+
* @since 3.1.0
|
38 |
+
* @access public
|
39 |
+
*/
|
40 |
+
public function display() {
|
41 |
+
?>
|
42 |
+
<table class="wp-list-table <?php esc_attr( implode( ' ', $this->get_table_classes() ) ); ?>">
|
43 |
+
<thead>
|
44 |
+
<tr>
|
45 |
+
<?php $this->print_column_headers(); ?>
|
46 |
+
</tr>
|
47 |
+
</thead>
|
48 |
+
|
49 |
+
<tbody id="the-list">
|
50 |
+
<?php $this->display_rows_or_placeholder(); ?>
|
51 |
+
</tbody>
|
52 |
+
|
53 |
+
<tfoot>
|
54 |
+
<tr>
|
55 |
+
<?php $this->print_column_headers( false ); ?>
|
56 |
+
</tr>
|
57 |
+
</tfoot>
|
58 |
+
|
59 |
+
</table>
|
60 |
+
<?php
|
61 |
+
}
|
62 |
+
}
|
classes/class-settings.php
CHANGED
@@ -143,7 +143,7 @@ class Settings {
|
|
143 |
|
144 |
$args['tooltip'] = esc_attr(
|
145 |
sprintf(
|
146 |
-
__(
|
147 |
$author->id,
|
148 |
$author->user_login,
|
149 |
$author->user_email,
|
@@ -263,7 +263,7 @@ class Settings {
|
|
263 |
'name' => 'records_ttl',
|
264 |
'title' => esc_html__( 'Keep Records for', 'stream' ),
|
265 |
'type' => 'number',
|
266 |
-
'class' => 'small-text
|
267 |
'desc' => esc_html__( 'Maximum number of days to keep activity records.', 'stream' ),
|
268 |
'default' => 30,
|
269 |
'min' => 1,
|
@@ -800,7 +800,7 @@ class Settings {
|
|
800 |
$count = isset( $users['avail_roles'][ $role_id ] ) ? $users['avail_roles'][ $role_id ] : 0;
|
801 |
|
802 |
if ( ! empty( $count ) ) {
|
803 |
-
$args['user_count'] = sprintf( _n( '
|
804 |
}
|
805 |
|
806 |
if ( $role_id === $author_or_role ) {
|
143 |
|
144 |
$args['tooltip'] = esc_attr(
|
145 |
sprintf(
|
146 |
+
__( 'ID: %1$d\nUser: %2$s\nEmail: %3$s\nRole: %4$s', 'stream' ),
|
147 |
$author->id,
|
148 |
$author->user_login,
|
149 |
$author->user_email,
|
263 |
'name' => 'records_ttl',
|
264 |
'title' => esc_html__( 'Keep Records for', 'stream' ),
|
265 |
'type' => 'number',
|
266 |
+
'class' => 'small-text',
|
267 |
'desc' => esc_html__( 'Maximum number of days to keep activity records.', 'stream' ),
|
268 |
'default' => 30,
|
269 |
'min' => 1,
|
800 |
$count = isset( $users['avail_roles'][ $role_id ] ) ? $users['avail_roles'][ $role_id ] : 0;
|
801 |
|
802 |
if ( ! empty( $count ) ) {
|
803 |
+
$args['user_count'] = sprintf( _n( '%d user', '%d users', absint( $count ), 'stream' ), absint( $count ) );
|
804 |
}
|
805 |
|
806 |
if ( $role_id === $author_or_role ) {
|
connectors/class-connector-buddypress.php
CHANGED
@@ -673,7 +673,7 @@ class Connector_BuddyPress extends Connector {
|
|
673 |
'mod' => esc_html_x( 'Moderator', 'buddypress', 'stream' ),
|
674 |
);
|
675 |
$message = sprintf(
|
676 |
-
__( 'Promoted "%s" to "%s" in "%s"', 'stream' ),
|
677 |
$user->display_name,
|
678 |
$roles[ $status ],
|
679 |
$group->name
|
@@ -685,7 +685,7 @@ class Connector_BuddyPress extends Connector {
|
|
685 |
$group = \groups_get_group( array( 'group_id' => $group_id ) );
|
686 |
$user = new \WP_User( $user_id );
|
687 |
$message = sprintf(
|
688 |
-
__( 'Demoted "%s" to "%s" in "%s"', 'stream' ),
|
689 |
$user->display_name,
|
690 |
_x( 'Member', 'buddypress', 'stream' ),
|
691 |
$group->name
|
673 |
'mod' => esc_html_x( 'Moderator', 'buddypress', 'stream' ),
|
674 |
);
|
675 |
$message = sprintf(
|
676 |
+
__( 'Promoted "%1$s" to "%2$s" in "%3$s"', 'stream' ),
|
677 |
$user->display_name,
|
678 |
$roles[ $status ],
|
679 |
$group->name
|
685 |
$group = \groups_get_group( array( 'group_id' => $group_id ) );
|
686 |
$user = new \WP_User( $user_id );
|
687 |
$message = sprintf(
|
688 |
+
__( 'Demoted "%1$s" to "%2$s" in "%3$s"', 'stream' ),
|
689 |
$user->display_name,
|
690 |
_x( 'Member', 'buddypress', 'stream' ),
|
691 |
$group->name
|
connectors/class-connector-gravityforms.php
CHANGED
@@ -481,7 +481,7 @@ class Connector_GravityForms extends Connector {
|
|
481 |
$forms_titles = wp_list_pluck( $forms, 'title' );
|
482 |
|
483 |
$this->log(
|
484 |
-
__( '%d %s imported', 'stream' ),
|
485 |
array(
|
486 |
'count' => $forms_total,
|
487 |
'label' => $forms_label,
|
481 |
$forms_titles = wp_list_pluck( $forms, 'title' );
|
482 |
|
483 |
$this->log(
|
484 |
+
__( '%1$d %2$s imported', 'stream' ),
|
485 |
array(
|
486 |
'count' => $forms_total,
|
487 |
'label' => $forms_label,
|
connectors/class-connector-user-switching.php
CHANGED
@@ -8,7 +8,7 @@ class Connector_User_Switching extends Connector {
|
|
8 |
*
|
9 |
* @var string
|
10 |
*/
|
11 |
-
public $name = '
|
12 |
|
13 |
/**
|
14 |
* Actions registered for this connector
|
8 |
*
|
9 |
* @var string
|
10 |
*/
|
11 |
+
public $name = 'userswitching';
|
12 |
|
13 |
/**
|
14 |
* Actions registered for this connector
|
connectors/class-connector-woocommerce.php
CHANGED
@@ -54,6 +54,8 @@ class Connector_Woocommerce extends Connector {
|
|
54 |
|
55 |
private $settings = array();
|
56 |
|
|
|
|
|
57 |
public function register() {
|
58 |
parent::register();
|
59 |
|
@@ -72,6 +74,7 @@ class Connector_Woocommerce extends Connector {
|
|
72 |
global $woocommerce;
|
73 |
|
74 |
if ( class_exists( 'WooCommerce' ) && version_compare( $woocommerce->version, self::PLUGIN_MIN_VERSION, '>=' ) ) {
|
|
|
75 |
return true;
|
76 |
}
|
77 |
|
@@ -413,14 +416,21 @@ class Connector_Woocommerce extends Connector {
|
|
413 |
return;
|
414 |
}
|
415 |
|
416 |
-
$old_status = wp_stream_is_vip() ? wpcom_vip_get_term_by( 'slug', $old, 'shop_order_status' ) : get_term_by( 'slug', $old, 'shop_order_status' );
|
417 |
-
$new_status = wp_stream_is_vip() ? wpcom_vip_get_term_by( 'slug', $new, 'shop_order_status' ) : get_term_by( 'slug', $new, 'shop_order_status' );
|
418 |
-
|
419 |
// Don't track new statuses
|
420 |
-
if (
|
421 |
return;
|
422 |
}
|
423 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
424 |
$message = esc_html_x(
|
425 |
'%1$s status changed from %2$s to %3$s',
|
426 |
'1. Order title, 2. Old status, 3. New status',
|
@@ -430,8 +440,6 @@ class Connector_Woocommerce extends Connector {
|
|
430 |
$order = new \WC_Order( $order_id );
|
431 |
$order_title = esc_html__( 'Order number', 'stream' ) . ' ' . esc_html( $order->get_order_number() );
|
432 |
$order_type_name = esc_html__( 'order', 'stream' );
|
433 |
-
$new_status_name = strtolower( $new_status->name );
|
434 |
-
$old_status_name = strtolower( $old_status->name );
|
435 |
|
436 |
$this->log(
|
437 |
$message,
|
@@ -446,7 +454,7 @@ class Connector_Woocommerce extends Connector {
|
|
446 |
),
|
447 |
$order_id,
|
448 |
'shop_order',
|
449 |
-
|
450 |
);
|
451 |
}
|
452 |
|
@@ -751,7 +759,7 @@ class Connector_Woocommerce extends Connector {
|
|
751 |
$shipping_method_settings = array();
|
752 |
$shipping_methods = $woocommerce->shipping();
|
753 |
|
754 |
-
foreach ( $shipping_methods->shipping_methods as $section_key => $shipping_method ) {
|
755 |
$title = $shipping_method->title;
|
756 |
$key = $shipping_method->plugin_id . $shipping_method->id . '_settings';
|
757 |
|
54 |
|
55 |
private $settings = array();
|
56 |
|
57 |
+
private $plugin_version = null;
|
58 |
+
|
59 |
public function register() {
|
60 |
parent::register();
|
61 |
|
74 |
global $woocommerce;
|
75 |
|
76 |
if ( class_exists( 'WooCommerce' ) && version_compare( $woocommerce->version, self::PLUGIN_MIN_VERSION, '>=' ) ) {
|
77 |
+
$this->plugin_version = $woocommerce->version;
|
78 |
return true;
|
79 |
}
|
80 |
|
416 |
return;
|
417 |
}
|
418 |
|
|
|
|
|
|
|
419 |
// Don't track new statuses
|
420 |
+
if ( empty( $old ) ) {
|
421 |
return;
|
422 |
}
|
423 |
|
424 |
+
if ( version_compare( $this->plugin_version, '2.2', '>=' ) ) {
|
425 |
+
$old_status_name = wc_get_order_status_name( $old );
|
426 |
+
$new_status_name = wc_get_order_status_name( $new );
|
427 |
+
} else {
|
428 |
+
$old_status = wp_stream_is_vip() ? wpcom_vip_get_term_by( 'slug', $old, 'shop_order_status' ) : get_term_by( 'slug', $old, 'shop_order_status' );
|
429 |
+
$new_status = wp_stream_is_vip() ? wpcom_vip_get_term_by( 'slug', $new, 'shop_order_status' ) : get_term_by( 'slug', $new, 'shop_order_status' );
|
430 |
+
$new_status_name = $new_status->name;
|
431 |
+
$old_status_name = $old_status->name;
|
432 |
+
}
|
433 |
+
|
434 |
$message = esc_html_x(
|
435 |
'%1$s status changed from %2$s to %3$s',
|
436 |
'1. Order title, 2. Old status, 3. New status',
|
440 |
$order = new \WC_Order( $order_id );
|
441 |
$order_title = esc_html__( 'Order number', 'stream' ) . ' ' . esc_html( $order->get_order_number() );
|
442 |
$order_type_name = esc_html__( 'order', 'stream' );
|
|
|
|
|
443 |
|
444 |
$this->log(
|
445 |
$message,
|
454 |
),
|
455 |
$order_id,
|
456 |
'shop_order',
|
457 |
+
'updated'
|
458 |
);
|
459 |
}
|
460 |
|
759 |
$shipping_method_settings = array();
|
760 |
$shipping_methods = $woocommerce->shipping();
|
761 |
|
762 |
+
foreach ( (array) $shipping_methods->shipping_methods as $section_key => $shipping_method ) {
|
763 |
$title = $shipping_method->title;
|
764 |
$key = $shipping_method->plugin_id . $shipping_method->id . '_settings';
|
765 |
|
connectors/class-connector-wordpress-seo.php
CHANGED
@@ -8,7 +8,7 @@ class Connector_WordPress_SEO extends Connector {
|
|
8 |
*
|
9 |
* @var string
|
10 |
*/
|
11 |
-
public $name = '
|
12 |
|
13 |
/**
|
14 |
* Holds tracked plugin minimum version required
|
@@ -89,6 +89,7 @@ class Connector_WordPress_SEO extends Connector {
|
|
89 |
'wpseo_xml' => esc_html_x( 'XML Sitemaps', 'wordpress-seo', 'stream' ),
|
90 |
'wpseo_permalinks' => esc_html_x( 'Permalinks', 'wordpress-seo', 'stream' ),
|
91 |
'wpseo_internal-links' => esc_html_x( 'Internal Links', 'wordpress-seo', 'stream' ),
|
|
|
92 |
'wpseo_rss' => esc_html_x( 'RSS', 'wordpress-seo', 'stream' ),
|
93 |
'wpseo_import' => esc_html_x( 'Import & Export', 'wordpress-seo', 'stream' ),
|
94 |
'wpseo_bulk-title-editor' => esc_html_x( 'Bulk Title Editor', 'wordpress-seo', 'stream' ),
|
@@ -176,6 +177,9 @@ class Connector_WordPress_SEO extends Connector {
|
|
176 |
}
|
177 |
|
178 |
public function register() {
|
|
|
|
|
|
|
179 |
parent::register();
|
180 |
|
181 |
foreach ( \WPSEO_Options::$options as $class ) {
|
@@ -395,7 +399,7 @@ class Connector_WordPress_SEO extends Connector {
|
|
395 |
'pinterestverify' => esc_html_x( 'Pinterest', 'wordpress-seo', 'stream' ), # type = textinput
|
396 |
'yandexverify' => esc_html_x( 'Yandex Webmaster Tools', 'wordpress-seo', 'stream' ), # type = textinput
|
397 |
|
398 |
-
// wp-content/plugins/wordpress-seo/admin/pages/
|
399 |
'breadcrumbs-enable' => esc_html_x( 'Enable Breadcrumbs', 'wordpress-seo', 'stream' ), # type = checkbox
|
400 |
'breadcrumbs-sep' => esc_html_x( 'Separator between breadcrumbs', 'wordpress-seo', 'stream' ), # type = textinput
|
401 |
'breadcrumbs-home' => esc_html_x( 'Anchor text for the Homepage', 'wordpress-seo', 'stream' ), # type = textinput
|
@@ -405,6 +409,7 @@ class Connector_WordPress_SEO extends Connector {
|
|
405 |
'breadcrumbs-404crumb' => esc_html_x( 'Breadcrumb for 404 Page', 'wordpress-seo', 'stream' ), # type = textinput
|
406 |
'breadcrumbs-blog-remove' => esc_html_x( 'Remove Blog page from Breadcrumbs', 'wordpress-seo', 'stream' ), # type = checkbox
|
407 |
'breadcrumbs-boldlast' => esc_html_x( 'Bold the last page in the breadcrumb', 'wordpress-seo', 'stream' ), # type = checkbox
|
|
|
408 |
|
409 |
// wp-content/plugins/wordpress-seo/admin/pages/metas.php:
|
410 |
'forcerewritetitle' => esc_html_x( 'Force rewrite titles', 'wordpress-seo', 'stream' ), # type = checkbox
|
@@ -439,21 +444,41 @@ class Connector_WordPress_SEO extends Connector {
|
|
439 |
// wp-content/plugins/wordpress-seo/admin/pages/social.php:
|
440 |
'opengraph' => esc_html_x( 'Add Open Graph meta data', 'wordpress-seo', 'stream' ), # type = checkbox
|
441 |
'facebook_site' => esc_html_x( 'Facebook Page URL', 'wordpress-seo', 'stream' ), # type = textinput
|
|
|
|
|
|
|
|
|
|
|
|
|
442 |
'og_frontpage_image' => esc_html_x( 'Image URL', 'wordpress-seo', 'stream' ), # type = textinput
|
443 |
'og_frontpage_desc' => esc_html_x( 'Description', 'wordpress-seo', 'stream' ), # type = textinput
|
|
|
444 |
'og_default_image' => esc_html_x( 'Image URL', 'wordpress-seo', 'stream' ), # type = textinput
|
445 |
'twitter' => esc_html_x( 'Add Twitter card meta data', 'wordpress-seo', 'stream' ), # type = checkbox
|
446 |
'twitter_site' => esc_html_x( 'Site Twitter Username', 'wordpress-seo', 'stream' ), # type = textinput
|
447 |
'twitter_card_type' => esc_html_x( 'The default card type to use', 'wordpress-seo', 'stream' ), # type = select
|
448 |
'googleplus' => esc_html_x( 'Add Google+ specific post meta data (excluding author metadata)', 'wordpress-seo', 'stream' ), # type = checkbox
|
449 |
'plus-publisher' => esc_html_x( 'Google Publisher Page', 'wordpress-seo', 'stream' ), # type = textinput
|
|
|
450 |
|
451 |
// wp-content/plugins/wordpress-seo/admin/pages/xml-sitemaps.php:
|
452 |
-
'enablexmlsitemap'
|
453 |
-
'disable_author_sitemap'
|
454 |
-
'
|
455 |
-
'
|
456 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
457 |
|
458 |
// Added manually
|
459 |
'rssbefore' => esc_html_x( 'Content to put before each post in the feed', 'wordpress-seo', 'stream' ),
|
8 |
*
|
9 |
* @var string
|
10 |
*/
|
11 |
+
public $name = 'wordpressseo';
|
12 |
|
13 |
/**
|
14 |
* Holds tracked plugin minimum version required
|
89 |
'wpseo_xml' => esc_html_x( 'XML Sitemaps', 'wordpress-seo', 'stream' ),
|
90 |
'wpseo_permalinks' => esc_html_x( 'Permalinks', 'wordpress-seo', 'stream' ),
|
91 |
'wpseo_internal-links' => esc_html_x( 'Internal Links', 'wordpress-seo', 'stream' ),
|
92 |
+
'wpseo_advanced' => esc_html_x( 'Advanced', 'wordpress-seo', 'stream' ),
|
93 |
'wpseo_rss' => esc_html_x( 'RSS', 'wordpress-seo', 'stream' ),
|
94 |
'wpseo_import' => esc_html_x( 'Import & Export', 'wordpress-seo', 'stream' ),
|
95 |
'wpseo_bulk-title-editor' => esc_html_x( 'Bulk Title Editor', 'wordpress-seo', 'stream' ),
|
177 |
}
|
178 |
|
179 |
public function register() {
|
180 |
+
if ( is_network_admin() && ! is_plugin_active_for_network( 'wordpress-seo/wordpress-seo-main.php' ) ) {
|
181 |
+
return;
|
182 |
+
}
|
183 |
parent::register();
|
184 |
|
185 |
foreach ( \WPSEO_Options::$options as $class ) {
|
399 |
'pinterestverify' => esc_html_x( 'Pinterest', 'wordpress-seo', 'stream' ), # type = textinput
|
400 |
'yandexverify' => esc_html_x( 'Yandex Webmaster Tools', 'wordpress-seo', 'stream' ), # type = textinput
|
401 |
|
402 |
+
// wp-content/plugins/wordpress-seo/admin/pages/advanced.php:
|
403 |
'breadcrumbs-enable' => esc_html_x( 'Enable Breadcrumbs', 'wordpress-seo', 'stream' ), # type = checkbox
|
404 |
'breadcrumbs-sep' => esc_html_x( 'Separator between breadcrumbs', 'wordpress-seo', 'stream' ), # type = textinput
|
405 |
'breadcrumbs-home' => esc_html_x( 'Anchor text for the Homepage', 'wordpress-seo', 'stream' ), # type = textinput
|
409 |
'breadcrumbs-404crumb' => esc_html_x( 'Breadcrumb for 404 Page', 'wordpress-seo', 'stream' ), # type = textinput
|
410 |
'breadcrumbs-blog-remove' => esc_html_x( 'Remove Blog page from Breadcrumbs', 'wordpress-seo', 'stream' ), # type = checkbox
|
411 |
'breadcrumbs-boldlast' => esc_html_x( 'Bold the last page in the breadcrumb', 'wordpress-seo', 'stream' ), # type = checkbox
|
412 |
+
'post_types-post-maintax' => esc_html_x( 'Taxonomy to show in breadcrumbs for post types', 'wordpress-seo', 'stream' ), # type = select
|
413 |
|
414 |
// wp-content/plugins/wordpress-seo/admin/pages/metas.php:
|
415 |
'forcerewritetitle' => esc_html_x( 'Force rewrite titles', 'wordpress-seo', 'stream' ), # type = checkbox
|
444 |
// wp-content/plugins/wordpress-seo/admin/pages/social.php:
|
445 |
'opengraph' => esc_html_x( 'Add Open Graph meta data', 'wordpress-seo', 'stream' ), # type = checkbox
|
446 |
'facebook_site' => esc_html_x( 'Facebook Page URL', 'wordpress-seo', 'stream' ), # type = textinput
|
447 |
+
'instagram_url' => esc_html_x( 'Instagram URL', 'wordpress-seo', 'stream' ), # type = textinput
|
448 |
+
'linkedin_url' => esc_html_x( 'LinkedIn URL', 'wordpress-seo', 'stream' ), # type = textinput
|
449 |
+
'myspace_url' => esc_html_x( 'MySpace URL', 'wordpress-seo', 'stream' ), # type = textinput
|
450 |
+
'pinterest_url' => esc_html_x( 'Pinterest URL', 'wordpress-seo', 'stream' ), # type = textinput
|
451 |
+
'youtube_url' => esc_html_x( 'YouTube URL', 'wordpress-seo', 'stream' ), # type = textinput
|
452 |
+
'google_plus_url' => esc_html_x( 'Google+ URL', 'wordpress-seo', 'stream' ), # type = textinput
|
453 |
'og_frontpage_image' => esc_html_x( 'Image URL', 'wordpress-seo', 'stream' ), # type = textinput
|
454 |
'og_frontpage_desc' => esc_html_x( 'Description', 'wordpress-seo', 'stream' ), # type = textinput
|
455 |
+
'og_frontpage_title' => esc_html_x( 'Title', 'wordpress-seo', 'stream' ), # type = textinput
|
456 |
'og_default_image' => esc_html_x( 'Image URL', 'wordpress-seo', 'stream' ), # type = textinput
|
457 |
'twitter' => esc_html_x( 'Add Twitter card meta data', 'wordpress-seo', 'stream' ), # type = checkbox
|
458 |
'twitter_site' => esc_html_x( 'Site Twitter Username', 'wordpress-seo', 'stream' ), # type = textinput
|
459 |
'twitter_card_type' => esc_html_x( 'The default card type to use', 'wordpress-seo', 'stream' ), # type = select
|
460 |
'googleplus' => esc_html_x( 'Add Google+ specific post meta data (excluding author metadata)', 'wordpress-seo', 'stream' ), # type = checkbox
|
461 |
'plus-publisher' => esc_html_x( 'Google Publisher Page', 'wordpress-seo', 'stream' ), # type = textinput
|
462 |
+
'fbadminapp' => esc_html_x( 'Facebook App ID', 'wordpress-seo', 'stream' ), # type = textinput
|
463 |
|
464 |
// wp-content/plugins/wordpress-seo/admin/pages/xml-sitemaps.php:
|
465 |
+
'enablexmlsitemap' => esc_html_x( 'Check this box to enable XML sitemap functionality.', 'wordpress-seo', 'stream' ), # type = checkbox
|
466 |
+
'disable_author_sitemap' => esc_html_x( 'Disable author/user sitemap', 'wordpress-seo', 'stream' ), # type = checkbox
|
467 |
+
'disable_author_noposts' => esc_html_x( 'Users with zero posts', 'wordpress-seo', 'stream' ), # type = checkbox
|
468 |
+
'user_role-administrator-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Administrator', 'wordpress-seo', 'stream' ), # type = checkbox
|
469 |
+
'user_role-editor-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Editor', 'wordpress-seo', 'stream' ), # type = checkbox
|
470 |
+
'user_role-author-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Author', 'wordpress-seo', 'stream' ), # type = checkbox
|
471 |
+
'user_role-contributor-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Contributor', 'wordpress-seo', 'stream' ), # type = checkbox
|
472 |
+
'user_role-subscriber-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Subscriber', 'wordpress-seo', 'stream' ), # type = checkbox
|
473 |
+
'xml_ping_yahoo' => esc_html_x( 'Ping Yahoo!', 'wordpress-seo', 'stream' ), # type = checkbox
|
474 |
+
'xml_ping_ask' => esc_html_x( 'Ping Ask.com', 'wordpress-seo', 'stream' ), # type = checkbox
|
475 |
+
'entries-per-page' => esc_html_x( 'Max entries per sitemap page', 'wordpress-seo', 'stream' ), # type = textinput
|
476 |
+
'excluded-posts' => esc_html_x( 'Posts to exclude', 'wordpress-seo', 'stream' ), # type = textinput
|
477 |
+
'post_types-post-not_in_sitemap' => _x( 'Post Types Posts (<code>post</code>)', 'wordpress-seo', 'stream' ), # type = checkbox
|
478 |
+
'post_types-page-not_in_sitemap' => _x( 'Post Types Pages (<code>page</code>)', 'wordpress-seo', 'stream' ), # type = checkbox
|
479 |
+
'post_types-attachment-not_in_sitemap' => _x( 'Post Types Media (<code>attachment</code>)', 'wordpress-seo', 'stream' ), # type = checkbox
|
480 |
+
'taxonomies-category-not_in_sitemap' => _x( 'Taxonomies Categories (<code>category</code>)', 'wordpress-seo', 'stream' ), # type = checkbox
|
481 |
+
'taxonomies-post_tag-not_in_sitemap' => _x( 'Taxonomies Tags (<code>post_tag</code>)', 'wordpress-seo', 'stream' ), # type = checkbox
|
482 |
|
483 |
// Added manually
|
484 |
'rssbefore' => esc_html_x( 'Content to put before each post in the feed', 'wordpress-seo', 'stream' ),
|
exporters/class-exporter-csv.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
namespace WP_Stream;
|
3 |
|
4 |
-
class Exporter_CSV extends Exporter{
|
5 |
/**
|
6 |
* Exporter name
|
7 |
*
|
1 |
<?php
|
2 |
namespace WP_Stream;
|
3 |
|
4 |
+
class Exporter_CSV extends Exporter {
|
5 |
/**
|
6 |
* Exporter name
|
7 |
*
|
includes/db-updates.php
CHANGED
@@ -1,4 +1,21 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
/**
|
3 |
* Version 3.0.2
|
4 |
*
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* Version 3.0.8
|
4 |
+
*
|
5 |
+
* Force update for older versions to call \dbdelta in install() method to fix column widths.
|
6 |
+
*
|
7 |
+
* @param string $db_version
|
8 |
+
* @param string $current_version
|
9 |
+
*
|
10 |
+
* @return string
|
11 |
+
*/
|
12 |
+
function wp_stream_update_auto_308( $db_version, $current_version ) {
|
13 |
+
$plugin = wp_stream_get_instance();
|
14 |
+
$plugin->install->install( $current_version );
|
15 |
+
|
16 |
+
return $current_version;
|
17 |
+
}
|
18 |
+
|
19 |
/**
|
20 |
* Version 3.0.2
|
21 |
*
|
readme.txt
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
=== Stream ===
|
2 |
-
Contributors: fjarrett, lukecarbis,
|
3 |
Tags: actions, activity, activity log, activity logs, admin actions, analytics, audit, audit log, audit logs, blackbox, black box, change, changes, dashboard, log, logs, stream, tracking, troubleshooting, wp stream
|
4 |
Requires at least: 3.9
|
5 |
Tested up to: 4.6
|
6 |
-
Stable tag: 3.
|
7 |
License: GPLv2 or later
|
8 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
@@ -79,6 +79,18 @@ Thank you for wanting to make Stream better for everyone!
|
|
79 |
|
80 |
== Changelog ==
|
81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
= 3.0.7 - June 14, 2016 =
|
83 |
|
84 |
* Tweak: Use get_sites instead of wp_get_sites when available ([#856](https://github.com/xwp/stream/pull/856))
|
1 |
=== Stream ===
|
2 |
+
Contributors: fjarrett, lukecarbis, stream, xwp
|
3 |
Tags: actions, activity, activity log, activity logs, admin actions, analytics, audit, audit log, audit logs, blackbox, black box, change, changes, dashboard, log, logs, stream, tracking, troubleshooting, wp stream
|
4 |
Requires at least: 3.9
|
5 |
Tested up to: 4.6
|
6 |
+
Stable tag: 3.1
|
7 |
License: GPLv2 or later
|
8 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
79 |
|
80 |
== Changelog ==
|
81 |
|
82 |
+
= 3.1 - October 31, 2016 =
|
83 |
+
|
84 |
+
* New: Stream Alerts is here! Get notified when something happens in your WP-Admin, so that you don't miss a thing. ([#844](https://github.com/xwp/stream/pull/844))
|
85 |
+
* Tweak: Better support for the latest version of Yoast SEO ([#838](https://github.com/xwp/stream/pull/838))
|
86 |
+
* Tweak: Better support for the latest version of WooCommerce ([#851](https://github.com/xwp/stream/pull/851)[#864](https://github.com/xwp/stream/pull/864))
|
87 |
+
* Tweak: Better taxonomy labelling ([#859](https://github.com/xwp/stream/pull/859))
|
88 |
+
* Fix: Fatal error caused by conflict with Yoast SEO ([#879](https://github.com/xwp/stream/pull/879))
|
89 |
+
* Fix: Activating Stream through WP CLI now works ([#880](https://github.com/xwp/stream/pull/880))
|
90 |
+
* Fix: Custom roles track properly ([#836](https://github.com/xwp/stream/pull/836))
|
91 |
+
|
92 |
+
Props [@chacha](https://github.com/chacha), [@lukecarbis](https://github.com/lukecarbis), [@johnbillion](https://github.com/johnbillion), [@rheinardkorf](https://github.com/rheinardkorf), [@frozzare](https://github.com/frozzare), [@johnregan3](https://github.com/johnregan3), [@jacobschweitzer](https://github.com/jacobschweitzer), [@wrongware](https://github.com/wrongware)
|
93 |
+
|
94 |
= 3.0.7 - June 14, 2016 =
|
95 |
|
96 |
* Tweak: Use get_sites instead of wp_get_sites when available ([#856](https://github.com/xwp/stream/pull/856))
|
stream.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Stream
|
4 |
* Plugin URI: https://wp-stream.com/
|
5 |
* Description: Stream tracks logged-in user activity so you can monitor every change made on your WordPress site in beautifully organized detail. All activity is organized by context, action and IP address for easy filtering. Developers can extend Stream with custom connectors to log any kind of action.
|
6 |
-
* Version: 3.
|
7 |
* Author: XWP
|
8 |
* Author URI: https://xwp.co/
|
9 |
* License: GPLv2+
|
3 |
* Plugin Name: Stream
|
4 |
* Plugin URI: https://wp-stream.com/
|
5 |
* Description: Stream tracks logged-in user activity so you can monitor every change made on your WordPress site in beautifully organized detail. All activity is organized by context, action and IP address for easy filtering. Developers can extend Stream with custom connectors to log any kind of action.
|
6 |
+
* Version: 3.1
|
7 |
* Author: XWP
|
8 |
* Author URI: https://xwp.co/
|
9 |
* License: GPLv2+
|
ui/css/admin.css
CHANGED
@@ -18,28 +18,28 @@
|
|
18 |
overflow: visible;
|
19 |
}
|
20 |
|
21 |
-
.
|
22 |
border-color: #ccc;
|
23 |
background: #f7f7f7;
|
24 |
-webkit-box-shadow: 0 1px 0 #ccc;
|
25 |
box-shadow: 0 1px 0 #ccc;
|
26 |
}
|
27 |
|
28 |
-
.
|
29 |
font-size: 0;
|
30 |
min-height: 28px;
|
31 |
}
|
32 |
|
33 |
-
.
|
34 |
border: solid #ccc 1px;
|
35 |
}
|
36 |
|
37 |
-
.
|
38 |
margin-top: 4px;
|
39 |
margin-bottom: 3px;
|
40 |
}
|
41 |
|
42 |
-
.
|
43 |
color: #555;
|
44 |
}
|
45 |
|
@@ -106,7 +106,7 @@
|
|
106 |
visibility: hidden;
|
107 |
}
|
108 |
|
109 |
-
.toplevel_page_wp_stream td.summary:hover .stream-filter-object-id
|
110 |
visibility: visible;
|
111 |
}
|
112 |
|
@@ -273,44 +273,44 @@
|
|
273 |
margin-right: 1em;
|
274 |
}
|
275 |
|
276 |
-
.
|
277 |
color: #a00;
|
278 |
}
|
279 |
|
280 |
-
.
|
281 |
color: #f00;
|
282 |
}
|
283 |
|
284 |
/* Date Interval Common */
|
285 |
|
286 |
-
.
|
287 |
width: 165px;
|
288 |
float: left;
|
289 |
margin-right: 6px;
|
290 |
margin-bottom: 6px;
|
291 |
}
|
292 |
|
293 |
-
.
|
294 |
float: left;
|
295 |
margin-right: 6px;
|
296 |
margin-bottom: 6px;
|
297 |
}
|
298 |
|
299 |
-
.
|
300 |
-
.
|
301 |
line-height: 28px;
|
302 |
height: 28px;
|
303 |
margin: 0;
|
304 |
width: 125px;
|
305 |
}
|
306 |
|
307 |
-
.
|
308 |
position: relative;
|
309 |
display: block;
|
310 |
float: left;
|
311 |
}
|
312 |
|
313 |
-
.
|
314 |
display: none;
|
315 |
position: absolute;
|
316 |
cursor: pointer;
|
@@ -324,11 +324,11 @@
|
|
324 |
padding-right: 2px;
|
325 |
}
|
326 |
|
327 |
-
.
|
328 |
content: '\f158';
|
329 |
}
|
330 |
|
331 |
-
.
|
332 |
display: block;
|
333 |
float: left;
|
334 |
border: 1px solid #ddd;
|
@@ -342,53 +342,53 @@
|
|
342 |
font-size: 14px;
|
343 |
}
|
344 |
|
345 |
-
.
|
346 |
content: '\f345';
|
347 |
}
|
348 |
|
349 |
|
350 |
/* Select2 Common */
|
351 |
|
352 |
-
.
|
353 |
-
.
|
354 |
background: none;
|
355 |
padding: 7px 7px 0;
|
356 |
color: #999;
|
357 |
}
|
358 |
|
359 |
-
.
|
360 |
color: #72777c;
|
361 |
}
|
362 |
|
363 |
-
.
|
364 |
background: transparent;
|
365 |
color: #aaa;
|
366 |
}
|
367 |
|
368 |
-
.
|
369 |
float: none;
|
370 |
margin-bottom: 4px;
|
371 |
margin-left: 2px;
|
372 |
}
|
373 |
|
374 |
-
.
|
375 |
margin: -3px 1px 0 -3px;
|
376 |
padding: 0;
|
377 |
width: 16px;
|
378 |
height: 16px;
|
379 |
}
|
380 |
|
381 |
-
.
|
382 |
padding-right: 8px;
|
383 |
}
|
384 |
|
385 |
-
.
|
386 |
-
.
|
387 |
font-size: 15px !important;
|
388 |
color: #656565;
|
389 |
}
|
390 |
|
391 |
-
.
|
392 |
-webkit-transition: none;
|
393 |
-moz-transition: none;
|
394 |
-o-transition: all 0 none;
|
@@ -470,11 +470,11 @@
|
|
470 |
border: 1px solid rgba(160,0,0,0.75);
|
471 |
}
|
472 |
|
473 |
-
.
|
474 |
font-weight: bold;
|
475 |
}
|
476 |
|
477 |
-
.
|
478 |
padding-left: 8px;
|
479 |
}
|
480 |
|
@@ -532,6 +532,22 @@
|
|
532 |
}
|
533 |
|
534 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
535 |
/* Extensions */
|
536 |
|
537 |
.post-type-stream_notification .view-switch {
|
18 |
overflow: visible;
|
19 |
}
|
20 |
|
21 |
+
.post-type-wp_stream_alerts .select2 .select2-selection {
|
22 |
border-color: #ccc;
|
23 |
background: #f7f7f7;
|
24 |
-webkit-box-shadow: 0 1px 0 #ccc;
|
25 |
box-shadow: 0 1px 0 #ccc;
|
26 |
}
|
27 |
|
28 |
+
.post-type-wp_stream_alerts .select2 .select2-selection--multiple {
|
29 |
font-size: 0;
|
30 |
min-height: 28px;
|
31 |
}
|
32 |
|
33 |
+
.post-type-wp_stream_alerts .select2-container.select2-container--focus .select2-selection--multiple {
|
34 |
border: solid #ccc 1px;
|
35 |
}
|
36 |
|
37 |
+
.post-type-wp_stream_alerts .select2-container .select2-selection--multiple .select2-selection__choice {
|
38 |
margin-top: 4px;
|
39 |
margin-bottom: 3px;
|
40 |
}
|
41 |
|
42 |
+
.post-type-wp_stream_alerts .select2 .select2-selection .select2-selection__rendered {
|
43 |
color: #555;
|
44 |
}
|
45 |
|
106 |
visibility: hidden;
|
107 |
}
|
108 |
|
109 |
+
.toplevel_page_wp_stream td.summary:hover .stream-filter-object-id{
|
110 |
visibility: visible;
|
111 |
}
|
112 |
|
273 |
margin-right: 1em;
|
274 |
}
|
275 |
|
276 |
+
.post-type-wp_stream_alerts a.warning {
|
277 |
color: #a00;
|
278 |
}
|
279 |
|
280 |
+
.post-type-wp_stream_alerts a.warning:hover {
|
281 |
color: #f00;
|
282 |
}
|
283 |
|
284 |
/* Date Interval Common */
|
285 |
|
286 |
+
.post-type-wp_stream_alerts .date-interval .field-predefined {
|
287 |
width: 165px;
|
288 |
float: left;
|
289 |
margin-right: 6px;
|
290 |
margin-bottom: 6px;
|
291 |
}
|
292 |
|
293 |
+
.post-type-wp_stream_alerts .date-interval .date-inputs {
|
294 |
float: left;
|
295 |
margin-right: 6px;
|
296 |
margin-bottom: 6px;
|
297 |
}
|
298 |
|
299 |
+
.post-type-wp_stream_alerts .date-interval .date-inputs .field-to,
|
300 |
+
.post-type-wp_stream_alerts .date-interval .date-inputs .field-from {
|
301 |
line-height: 28px;
|
302 |
height: 28px;
|
303 |
margin: 0;
|
304 |
width: 125px;
|
305 |
}
|
306 |
|
307 |
+
.post-type-wp_stream_alerts .date-interval .date-inputs .box {
|
308 |
position: relative;
|
309 |
display: block;
|
310 |
float: left;
|
311 |
}
|
312 |
|
313 |
+
.post-type-wp_stream_alerts .date-interval .date-inputs .box .date-remove {
|
314 |
display: none;
|
315 |
position: absolute;
|
316 |
cursor: pointer;
|
324 |
padding-right: 2px;
|
325 |
}
|
326 |
|
327 |
+
.post-type-wp_stream_alerts .date-interval .date-inputs .box .date-remove:before {
|
328 |
content: '\f158';
|
329 |
}
|
330 |
|
331 |
+
.post-type-wp_stream_alerts .date-interval .date-inputs .connector {
|
332 |
display: block;
|
333 |
float: left;
|
334 |
border: 1px solid #ddd;
|
342 |
font-size: 14px;
|
343 |
}
|
344 |
|
345 |
+
.post-type-wp_stream_alerts .date-interval .date-inputs .connector:before {
|
346 |
content: '\f345';
|
347 |
}
|
348 |
|
349 |
|
350 |
/* Select2 Common */
|
351 |
|
352 |
+
.post-type-wp_stream_alerts li.select2-searching,
|
353 |
+
.post-type-wp_stream_alerts li.select2-no-results {
|
354 |
background: none;
|
355 |
padding: 7px 7px 0;
|
356 |
color: #999;
|
357 |
}
|
358 |
|
359 |
+
.post-type-wp_stream_alerts .select2 .select2-selection .select2-selection__placeholder {
|
360 |
color: #72777c;
|
361 |
}
|
362 |
|
363 |
+
.post-type-wp_stream_alerts .select2-results .select2-disabled {
|
364 |
background: transparent;
|
365 |
color: #aaa;
|
366 |
}
|
367 |
|
368 |
+
.post-type-wp_stream_alerts .select2 .select2-search--inline {
|
369 |
float: none;
|
370 |
margin-bottom: 4px;
|
371 |
margin-left: 2px;
|
372 |
}
|
373 |
|
374 |
+
.post-type-wp_stream_alerts .select2-selection .icon16 {
|
375 |
margin: -3px 1px 0 -3px;
|
376 |
padding: 0;
|
377 |
width: 16px;
|
378 |
height: 16px;
|
379 |
}
|
380 |
|
381 |
+
.post-type-wp_stream_alerts .select2-selection .icon16 {
|
382 |
padding-right: 8px;
|
383 |
}
|
384 |
|
385 |
+
.post-type-wp_stream_alerts .select2-chosen .icon16:before,
|
386 |
+
.post-type-wp_stream_alerts .select2-search-choice .icon16:before {
|
387 |
font-size: 15px !important;
|
388 |
color: #656565;
|
389 |
}
|
390 |
|
391 |
+
.post-type-wp_stream_alerts .select2-search-choice-close {
|
392 |
-webkit-transition: none;
|
393 |
-moz-transition: none;
|
394 |
-o-transition: all 0 none;
|
470 |
border: 1px solid rgba(160,0,0,0.75);
|
471 |
}
|
472 |
|
473 |
+
.post-type-wp_stream_alerts .select2-results__option .parent {
|
474 |
font-weight: bold;
|
475 |
}
|
476 |
|
477 |
+
.post-type-wp_stream_alerts .select2-results__option .child {
|
478 |
padding-left: 8px;
|
479 |
}
|
480 |
|
532 |
}
|
533 |
|
534 |
|
535 |
+
.toplevel_page_wp_stream .alert-highlight.highlight-yellow {
|
536 |
+
background-color: #ffffe0;
|
537 |
+
}
|
538 |
+
|
539 |
+
.toplevel_page_wp_stream .alert-highlight.highlight-red {
|
540 |
+
background-color: #fbeaea;
|
541 |
+
}
|
542 |
+
|
543 |
+
.toplevel_page_wp_stream .alert-highlight.highlight-green {
|
544 |
+
background-color: #ecf7ed;
|
545 |
+
}
|
546 |
+
|
547 |
+
.toplevel_page_wp_stream .alert-highlight.highlight-blue {
|
548 |
+
background-color: #e5f5fa;
|
549 |
+
}
|
550 |
+
|
551 |
/* Extensions */
|
552 |
|
553 |
.post-type-stream_notification .view-switch {
|
ui/css/alerts-list.css
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.edit-php.post-type-wp_stream_alerts .inline-edit-col,
|
2 |
+
.edit-php.post-type-wp_stream_alerts .widefat .inline-edit-col,
|
3 |
+
.edit-php.post-type-wp_stream_alerts .widefat p {
|
4 |
+
color: #444;
|
5 |
+
font-size: 12px;
|
6 |
+
display: block;
|
7 |
+
margin: .2em 0;
|
8 |
+
line-height: 2.5;
|
9 |
+
}
|
10 |
+
.edit-php.post-type-wp_stream_alerts .inline-edit-col .wp_stream_alert_type_description {
|
11 |
+
line-height: 1.5em;
|
12 |
+
display: inline-block;
|
13 |
+
}
|
14 |
+
.edit-php.post-type-wp_stream_alerts .inline-edit-col {
|
15 |
+
padding: 0 0.5em !important;
|
16 |
+
}
|
17 |
+
|
18 |
+
.edit-php.post-type-wp_stream_alerts .inline-edit-col legend {
|
19 |
+
padding: 0.2em 0 !important;
|
20 |
+
color: #555;
|
21 |
+
}
|
22 |
+
|
23 |
+
.edit-php.post-type-wp_stream_alerts .inline-edit-col .select2-container {
|
24 |
+
display: block;
|
25 |
+
}
|
26 |
+
|
27 |
+
#wp_stream_alert_type_form {
|
28 |
+
max-height: 14em;
|
29 |
+
border: 1px solid #ddd;
|
30 |
+
overflow-y: scroll;
|
31 |
+
padding: 0.2em 0.5em;
|
32 |
+
margin: 6px 0;
|
33 |
+
background-color: #fff;
|
34 |
+
display: none;
|
35 |
+
}
|
36 |
+
|
37 |
+
#wp_stream_alert_type_form select {
|
38 |
+
width: 100%;
|
39 |
+
}
|
40 |
+
|
41 |
+
#wp_stream_alert_type_form .dashicons {
|
42 |
+
position: relative;
|
43 |
+
top: 7px;
|
44 |
+
left: -2px;
|
45 |
+
font-size: 1em;
|
46 |
+
}
|
47 |
+
|
48 |
+
.edit-php.post-type-wp_stream_alerts .misc-pub-section.misc-pub-post-status,
|
49 |
+
.edit-php.post-type-wp_stream_alerts #misc-publishing-actions {
|
50 |
+
padding: 0;
|
51 |
+
}
|
52 |
+
|
53 |
+
@media ( min-width: 781px ) {
|
54 |
+
.wp-stream-show-mobile {
|
55 |
+
display: none;
|
56 |
+
}
|
57 |
+
.edit-php.post-type-wp_stream_alerts .inline-edit-col.inline-edit-wp_stream_alerts {
|
58 |
+
float: left;
|
59 |
+
width: 100%;
|
60 |
+
max-width: 20%
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
.edit-php.post-type-wp_stream_alerts .select2 .select2-selection {
|
65 |
+
border-color: #ccc;
|
66 |
+
background: #f7f7f7;
|
67 |
+
-webkit-box-shadow: 0 1px 0 #ccc;
|
68 |
+
box-shadow: 0 1px 0 #ccc;
|
69 |
+
}
|
70 |
+
.edit-php.post-type-wp_stream_alerts label {
|
71 |
+
font-style: italic;
|
72 |
+
}
|
73 |
+
|
74 |
+
.edit-php.post-type-wp_stream_alerts select {
|
75 |
+
width: auto;
|
76 |
+
}
|
77 |
+
|
78 |
+
.edit-php.post-type-wp_stream_alerts span.select2-selection__rendered {
|
79 |
+
font-style: normal;
|
80 |
+
}
|
81 |
+
|
82 |
+
#add-new-alert.inline-edit-row.inline-edit-row-page .inline-edit-col-right {
|
83 |
+
margin-top: 32px;
|
84 |
+
}
|
85 |
+
.edit-php.post-type-wp_stream_alerts #add-new-alert .select2.select2-container {
|
86 |
+
display: block;
|
87 |
+
}
|
88 |
+
.edit-php.post-type-wp_stream_alerts #add-new-alert .inline-edit-add-new-notifications,
|
89 |
+
.edit-php.post-type-wp_stream_alerts #add-new-alert .inline-edit-add-new-status {
|
90 |
+
margin-top: 33px;
|
91 |
+
}
|
92 |
+
#add-new-alert .inline-edit-add-new-triggers label {
|
93 |
+
margin: .2em 0;
|
94 |
+
line-height: 2.5;
|
95 |
+
}
|
96 |
+
.post-type-wp_stream_alerts .select2-container {
|
97 |
+
margin-bottom: 6px;
|
98 |
+
min-width: 165px;
|
99 |
+
}
|
100 |
+
|
101 |
+
/* Alert List Page */
|
102 |
+
.post-type-wp_stream_alerts #posts-filter #post-query-submit {
|
103 |
+
display: none;
|
104 |
+
}
|
105 |
+
|
106 |
+
.post-type-wp_stream_alerts .wp-list-table .alert_trigger_value {
|
107 |
+
padding: 3px 20px 3px 10px;
|
108 |
+
border-top: 1px solid #e5e5e5;
|
109 |
+
border-bottom: 1px solid #e5e5e5;
|
110 |
+
background: #fff;
|
111 |
+
display: inline-block;
|
112 |
+
height: 22px;
|
113 |
+
line-height: 22px;
|
114 |
+
box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
|
115 |
+
}
|
116 |
+
|
117 |
+
.post-type-wp_stream_alerts .wp-list-table .alert_trigger_value:first-child {
|
118 |
+
border-left: 1px solid #e5e5e5;
|
119 |
+
}
|
120 |
+
|
121 |
+
.post-type-wp_stream_alerts .wp-list-table .alert_trigger_value:last-child {
|
122 |
+
padding-right: 10px;
|
123 |
+
border-right: 1px solid #e5e5e5;
|
124 |
+
}
|
125 |
+
|
126 |
+
.post-type-wp_stream_alerts .wp-list-table .alert_trigger_value:after {
|
127 |
+
content: "";
|
128 |
+
position: absolute;
|
129 |
+
margin-left: 7px;
|
130 |
+
margin-top: 6px;
|
131 |
+
display: inline-block;
|
132 |
+
height: 8px;
|
133 |
+
width: 8px;
|
134 |
+
transform: rotate(45deg);
|
135 |
+
border-top: 2px solid #e5e5e5;
|
136 |
+
border-right: 2px solid #e5e5e5;
|
137 |
+
}
|
138 |
+
|
139 |
+
.post-type-wp_stream_alerts .wp-list-table .alert_trigger_value:last-child:after {
|
140 |
+
border-top: none;
|
141 |
+
border-right: none;
|
142 |
+
}
|
ui/js/alerts-list.js
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* globals jQuery */
|
2 |
+
( function( $ ) {
|
3 |
+
$( document ).ready( function() {
|
4 |
+
$( '.inline-edit-col-left, .inline-edit-col-right, #major-publishing-actions', '.edit-php.post-type-wp_stream_alerts' ).each( function() {
|
5 |
+
$( this ).remove();
|
6 |
+
});
|
7 |
+
|
8 |
+
// This is done with JS instead of CSS to override the inline styles added by Select2's JS.
|
9 |
+
$( '.select2-container', '.inline-edit-col' ).css( { 'width': '100%' } );
|
10 |
+
});
|
11 |
+
})( jQuery );
|
ui/js/alerts.js
ADDED
@@ -0,0 +1,272 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* globals jQuery, streamAlerts, inlineEditPost */
|
2 |
+
jQuery( function( $ ) {
|
3 |
+
'use strict';
|
4 |
+
var $post_row,
|
5 |
+
$edit_row;
|
6 |
+
var setupSelectTwo = function setupSelectTwo( id ) {
|
7 |
+
var $target = $( id );
|
8 |
+
$target.find( '.select2-select.connector_or_context' ).each( function( k, el ) {
|
9 |
+
$( el ).select2({
|
10 |
+
allowClear: true,
|
11 |
+
placeholder: streamAlerts.anyContext,
|
12 |
+
templateResult: function( item ) {
|
13 |
+
if ( 'undefined' === typeof item.id ) {
|
14 |
+
return item.text;
|
15 |
+
}
|
16 |
+
if ( -1 === item.id.indexOf( '-' ) ) {
|
17 |
+
return $( '<span class="parent">' + item.text + '</span>' );
|
18 |
+
} else {
|
19 |
+
return $( '<span class="child">' + item.text + '</span>' );
|
20 |
+
}
|
21 |
+
},
|
22 |
+
matcher: function (params, data) {
|
23 |
+
var match = $.extend( true, {}, data );
|
24 |
+
|
25 |
+
if (null === params.term || '' === $.trim( params.term )) {
|
26 |
+
return match;
|
27 |
+
}
|
28 |
+
|
29 |
+
var term = params.term.toLowerCase();
|
30 |
+
|
31 |
+
match.id = match.id.replace( 'blogs', 'sites' );
|
32 |
+
if (match.id.toLowerCase().indexOf( term ) >= 0) {
|
33 |
+
return match;
|
34 |
+
}
|
35 |
+
|
36 |
+
if (match.children) {
|
37 |
+
for (var i = match.children.length - 1; i >= 0; i--) {
|
38 |
+
var child = match.children[i];
|
39 |
+
|
40 |
+
// Remove term from results if it doesn't match.
|
41 |
+
if (-1 === child.id.toLowerCase().indexOf( term )) {
|
42 |
+
match.children.splice( i, 1 );
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
if (match.children.length > 0) {
|
47 |
+
return match;
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
return null;
|
52 |
+
}
|
53 |
+
}).change(function () {
|
54 |
+
var value = $( this ).val();
|
55 |
+
if (value) {
|
56 |
+
var parts = value.split( '-' );
|
57 |
+
$( this ).siblings( '.connector' ).val( parts[0] );
|
58 |
+
$( this ).siblings( '.context' ).val( parts[1] );
|
59 |
+
// $(this).removeAttr('name');
|
60 |
+
}
|
61 |
+
});
|
62 |
+
|
63 |
+
var parts = [
|
64 |
+
$( el ).siblings( '.connector' ).val(),
|
65 |
+
$( el ).siblings( '.context' ).val()
|
66 |
+
];
|
67 |
+
if ('' === parts[1]) {
|
68 |
+
parts.splice( 1, 1 );
|
69 |
+
}
|
70 |
+
$( el ).val( parts.join( '-' ) ).trigger( 'change' );
|
71 |
+
});
|
72 |
+
|
73 |
+
$target.find( 'select.select2-select:not(.connector_or_context)' ).each(function () {
|
74 |
+
var element_id_split = $( this ).attr( 'id' ).split( '_' );
|
75 |
+
var select_name = element_id_split[element_id_split.length - 1].charAt( 0 ).toUpperCase() +
|
76 |
+
element_id_split[element_id_split.length - 1].slice( 1 );
|
77 |
+
$( this ).select2({
|
78 |
+
allowClear: true,
|
79 |
+
placeholder: streamAlerts.any + ' ' + select_name
|
80 |
+
});
|
81 |
+
});
|
82 |
+
};
|
83 |
+
var $alertSettingSelect = $( '#wp_stream_alert_type' );
|
84 |
+
|
85 |
+
var loadAlertSettings = function( alert_type ) {
|
86 |
+
var data = {
|
87 |
+
'action' : 'load_alerts_settings',
|
88 |
+
'alert_type' : alert_type
|
89 |
+
};
|
90 |
+
|
91 |
+
var $edit_row = $( '#wp_stream_alert_type' ).closest( 'tr' );
|
92 |
+
var row_id = $edit_row.attr( 'id' );
|
93 |
+
data.post_id = row_id.split('-')[1];
|
94 |
+
$.post( window.ajaxurl, data, function( response ) {
|
95 |
+
var $alert_type_settings = $( '#wp_stream_alert_type_form' );
|
96 |
+
var alert_type = $( '#wp_stream_alert_type' ).val();
|
97 |
+
if ('none' === alert_type) {
|
98 |
+
$alert_type_settings.hide();
|
99 |
+
return;
|
100 |
+
}
|
101 |
+
$alert_type_settings.html( response.data.html );
|
102 |
+
$alert_type_settings.show();
|
103 |
+
});
|
104 |
+
};
|
105 |
+
|
106 |
+
$( '#the-list' ).on('change', '#wp_stream_trigger_connector_or_context', function() {
|
107 |
+
if ( 'wp_stream_trigger_connector_or_context' === $( this ).attr( 'id' ) ) {
|
108 |
+
var connector = $( this ).val();
|
109 |
+
if ( connector && 0 < connector.indexOf( '-' ) ) {
|
110 |
+
var connector_split = connector.split( '-' );
|
111 |
+
connector = connector_split[0];
|
112 |
+
}
|
113 |
+
getActions( connector );
|
114 |
+
}
|
115 |
+
});
|
116 |
+
|
117 |
+
var getActions = function( connector ) {
|
118 |
+
var trigger_action = $( '#wp_stream_trigger_action' );
|
119 |
+
trigger_action.empty();
|
120 |
+
trigger_action.prop( 'disabled', true );
|
121 |
+
|
122 |
+
var placeholder = $( '<option/>', {value: '', text: ''} );
|
123 |
+
trigger_action.append( placeholder );
|
124 |
+
|
125 |
+
var data = {
|
126 |
+
'action' : 'get_actions',
|
127 |
+
'connector' : connector
|
128 |
+
};
|
129 |
+
|
130 |
+
$.post( window.ajaxurl, data, function( response ) {
|
131 |
+
var success = response.success,
|
132 |
+
actions = response.data;
|
133 |
+
if ( ! success ) {
|
134 |
+
return;
|
135 |
+
}
|
136 |
+
for ( var key in actions ) {
|
137 |
+
if ( actions.hasOwnProperty( key ) ) {
|
138 |
+
var value = actions[key];
|
139 |
+
var option = $( '<option/>', {value: key, text: value} );
|
140 |
+
trigger_action.append( option );
|
141 |
+
}
|
142 |
+
}
|
143 |
+
trigger_action.prop( 'disabled', false );
|
144 |
+
$( document ).trigger( 'alert-actions-updated' );
|
145 |
+
});
|
146 |
+
};
|
147 |
+
|
148 |
+
$alertSettingSelect.change( function() {
|
149 |
+
loadAlertSettings( $( this ).val() );
|
150 |
+
});
|
151 |
+
|
152 |
+
$( '#wpbody-content' ).on( 'click', 'a.page-title-action', function( e ) {
|
153 |
+
e.preventDefault();
|
154 |
+
$( '#add-new-alert' ).remove();
|
155 |
+
if ( $( '.inline-edit-wp_stream_alerts' ).length > 0 ) {
|
156 |
+
$( '.inline-edit-wp_stream_alerts .inline-edit-save button.button-secondary.cancel' ).trigger( 'click' );
|
157 |
+
}
|
158 |
+
var alert_form_html = '';
|
159 |
+
var data = {
|
160 |
+
'action': 'get_new_alert_triggers_notifications'
|
161 |
+
};
|
162 |
+
$.post( window.ajaxurl, data, function( response ) {
|
163 |
+
if ( true === response.success ) {
|
164 |
+
alert_form_html = response.data.html;
|
165 |
+
$( 'tbody#the-list' ).prepend( '<tr id="add-new-alert" class="inline-edit-row inline-edit-row-page inline-edit-page quick-edit-row quick-edit-row-page inline-edit-page inline-editor" style=""><td colspan="4" class="colspanchange">' + alert_form_html + '<p class="submit inline-edit-save"> <button type="button" class="button-secondary cancel alignleft">Cancel</button> <input type="hidden" id="_inline_edit" name="_inline_edit" value="3550d271fe"> <button type="button" class="button-primary save alignright">Save</button> <span class="spinner"></span><span class="error" style="display:none"></span> <br class="clear"></p></td></tr>' );
|
166 |
+
var add_new_alert = $( '#add-new-alert' );
|
167 |
+
var current_bg_color = add_new_alert.css( 'background-color' );
|
168 |
+
|
169 |
+
// Color taken from /wp-admin/css/forms.css
|
170 |
+
// #pass-strength-result.strong
|
171 |
+
add_new_alert.css( 'background-color', '#C1E1B9' );
|
172 |
+
setTimeout(function () {
|
173 |
+
add_new_alert.css( 'background-color', current_bg_color );
|
174 |
+
}, 250);
|
175 |
+
|
176 |
+
$( '#wp_stream_alert_type' ).change( function () {
|
177 |
+
loadAlertSettings( $( this ).val() );
|
178 |
+
});
|
179 |
+
add_new_alert.on( 'click', '.button-secondary.cancel', function () {
|
180 |
+
$( '#add-new-alert' ).remove();
|
181 |
+
});
|
182 |
+
add_new_alert.on( 'click', '.button-primary.save', save_new_alert );
|
183 |
+
|
184 |
+
setupSelectTwo( '#add-new-alert' );
|
185 |
+
}
|
186 |
+
});
|
187 |
+
|
188 |
+
});
|
189 |
+
var save_new_alert = function save_new_alert( e ) {
|
190 |
+
e.preventDefault();
|
191 |
+
$( '#add-new-alert' ).find( 'p.submit.inline-edit-save span.spinner' ).css( 'visibility', 'visible' );
|
192 |
+
var data = {
|
193 |
+
'action': 'save_new_alert',
|
194 |
+
'wp_stream_alerts_nonce': $( '#wp_stream_alerts_nonce' ).val(),
|
195 |
+
'wp_stream_trigger_author': $( '#wp_stream_trigger_author' ).val(),
|
196 |
+
'wp_stream_trigger_context': $( '#wp_stream_trigger_connector_or_context' ).val(),
|
197 |
+
'wp_stream_trigger_action': $( '#wp_stream_trigger_action' ).val(),
|
198 |
+
'wp_stream_alert_type': $( '#wp_stream_alert_type' ).val(),
|
199 |
+
'wp_stream_alert_status': $( '#wp_stream_alert_status' ).val()
|
200 |
+
};
|
201 |
+
$( '#wp_stream_alert_type_form' ).find( ':input' ).each( function(){
|
202 |
+
var alert_type_data_id = $( this ).attr( 'id' );
|
203 |
+
if ( $( this ).val() ) {
|
204 |
+
data[alert_type_data_id] = $( this ).val();
|
205 |
+
}
|
206 |
+
});
|
207 |
+
|
208 |
+
$.post( window.ajaxurl, data, function( response ) {
|
209 |
+
if ( true === response.success ) {
|
210 |
+
$( '#add-new-alert' ).find( 'p.submit.inline-edit-save span.spinner' ).css( 'visibility', 'hidden' );
|
211 |
+
location.reload();
|
212 |
+
}
|
213 |
+
});
|
214 |
+
};
|
215 |
+
|
216 |
+
// we create a copy of the WP inline edit post function
|
217 |
+
var $wp_inline_edit = inlineEditPost.edit;
|
218 |
+
|
219 |
+
// and then we overwrite the function with our own code
|
220 |
+
inlineEditPost.edit = function( id ) {
|
221 |
+
// "call" the original WP edit function
|
222 |
+
// we don't want to leave WordPress hanging
|
223 |
+
$wp_inline_edit.apply( this, arguments );
|
224 |
+
|
225 |
+
// now we take care of our business
|
226 |
+
|
227 |
+
// get the post ID
|
228 |
+
var post_id = 0;
|
229 |
+
if ( typeof( id ) === 'object' ) {
|
230 |
+
post_id = parseInt( this.getId( id ), 10 );
|
231 |
+
}
|
232 |
+
|
233 |
+
if ( post_id > 0 ) {
|
234 |
+
// define the edit row
|
235 |
+
$edit_row = $( '#edit-' + post_id );
|
236 |
+
$post_row = $( '#post-' + post_id );
|
237 |
+
|
238 |
+
// get the data
|
239 |
+
var alert_trigger_connector = $post_row.find( 'input[name="wp_stream_trigger_connector"]' ).val();
|
240 |
+
var alert_trigger_context = $post_row.find( 'input[name="wp_stream_trigger_context"]' ).val();
|
241 |
+
var alert_trigger_connector_context = alert_trigger_connector + '-' + alert_trigger_context;
|
242 |
+
var alert_trigger_action = $post_row.find( 'input[name="wp_stream_trigger_action"]' ).val();
|
243 |
+
var alert_status = $post_row.find( 'input[name="wp_stream_alert_status"]' ).val();
|
244 |
+
|
245 |
+
// populate the data
|
246 |
+
$edit_row.find( 'input[name="wp_stream_trigger_connector"]' ).attr( 'value', alert_trigger_connector );
|
247 |
+
$edit_row.find( 'input[name="wp_stream_trigger_context"]' ).attr( 'value', alert_trigger_context );
|
248 |
+
$edit_row.find( 'select[name="wp_stream_trigger_connector_or_context"] option[value="' + alert_trigger_connector_context + '"]' ).attr( 'selected', 'selected' );
|
249 |
+
$( document ).one( 'alert-actions-updated', function() {
|
250 |
+
$edit_row.find( 'input[name="wp_stream_trigger_action"]' ).attr( 'value', alert_trigger_action );
|
251 |
+
$edit_row.find( 'select[name="wp_stream_trigger_action"] option[value="' + alert_trigger_action + '"]' ).attr( 'selected', 'selected' ).trigger( 'change' );
|
252 |
+
});
|
253 |
+
$edit_row.find( 'select[name="wp_stream_alert_status"] option[value="' + alert_status + '"]' ).attr( 'selected', 'selected' );
|
254 |
+
setupSelectTwo( '#edit-' + post_id );
|
255 |
+
|
256 |
+
// Alert type handling
|
257 |
+
$( '#wp_stream_alert_type_form' ).hide();
|
258 |
+
var alert_type = $post_row.find( 'input[name="wp_stream_alert_type"]' ).val();
|
259 |
+
$edit_row.find( 'select[name="wp_stream_alert_type"] option[value="' + alert_type + '"]' ).attr( 'selected', 'selected' ).trigger( 'change' );
|
260 |
+
}
|
261 |
+
};
|
262 |
+
if ( window.location.hash ) {
|
263 |
+
var $target_post_row = $( window.location.hash );
|
264 |
+
if ( $target_post_row.length ) {
|
265 |
+
var scroll_to_position = $target_post_row.offset().top - $('#wpadminbar').height();
|
266 |
+
$('html, body').animate({
|
267 |
+
scrollTop: scroll_to_position
|
268 |
+
}, 1000);
|
269 |
+
$target_post_row.find('.row-actions a.editinline').trigger('click');
|
270 |
+
}
|
271 |
+
}
|
272 |
+
});
|
ui/js/live-updates.js
CHANGED
@@ -46,7 +46,8 @@ jQuery( function( $ ) {
|
|
46 |
$new_items = $( data['wp-stream-heartbeat'] );
|
47 |
|
48 |
// Remove all default classes and add class to highlight new rows
|
49 |
-
$new_items.
|
|
|
50 |
|
51 |
// Check if first tr has the alternate class
|
52 |
var has_class = ( $current_items.first().hasClass( 'alternate' ) );
|
46 |
$new_items = $( data['wp-stream-heartbeat'] );
|
47 |
|
48 |
// Remove all default classes and add class to highlight new rows
|
49 |
+
$new_items.addClass( 'new-row' );
|
50 |
+
|
51 |
|
52 |
// Check if first tr has the alternate class
|
53 |
var has_class = ( $current_items.first().hasClass( 'alternate' ) );
|
ui/js/settings.js
CHANGED
@@ -1,8 +1,13 @@
|
|
1 |
/* globals confirm, wp_stream, ajaxurl, wp_stream_regenerate_alt_rows */
|
2 |
jQuery( function( $ ) {
|
3 |
-
|
4 |
-
|
5 |
-
|
|
|
|
|
|
|
|
|
|
|
6 |
keepRecordsForRow = keepRecordsFor.closest( 'tr' );
|
7 |
|
8 |
function toggleKeepRecordsFor() {
|
@@ -20,7 +25,6 @@ jQuery( function( $ ) {
|
|
20 |
});
|
21 |
|
22 |
toggleKeepRecordsFor();
|
23 |
-
|
24 |
// Confirmation on some important actions
|
25 |
$( '#wp_stream_general_reset_site_settings' ).click( function( e ) {
|
26 |
if ( ! confirm( wp_stream.i18n.confirm_defaults ) ) {
|
1 |
/* globals confirm, wp_stream, ajaxurl, wp_stream_regenerate_alt_rows */
|
2 |
jQuery( function( $ ) {
|
3 |
+
var network_affix;
|
4 |
+
if ( 'wp_stream_network' === $( 'input[name="option_page"]' ).val() ) {
|
5 |
+
network_affix = '_network_affix';
|
6 |
+
} else {
|
7 |
+
network_affix = '';
|
8 |
+
}
|
9 |
+
var keepRecordsIndefinitely = $( '#wp_stream' + network_affix + '\\[general_keep_records_indefinitely\\]' ),
|
10 |
+
keepRecordsFor = $( '#wp_stream' + network_affix + '_general_records_ttl' ),
|
11 |
keepRecordsForRow = keepRecordsFor.closest( 'tr' );
|
12 |
|
13 |
function toggleKeepRecordsFor() {
|
25 |
});
|
26 |
|
27 |
toggleKeepRecordsFor();
|
|
|
28 |
// Confirmation on some important actions
|
29 |
$( '#wp_stream_general_reset_site_settings' ).click( function( e ) {
|
30 |
if ( ! confirm( wp_stream.i18n.confirm_defaults ) ) {
|