PluginProbe
wpForo Forum / 2.2.3
wpForo Forum v2.2.3
3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.2 All 137 releases
wpforo / modules / subscriptions / Subscriptions.php

Subscriptions.php in wpForo Forum 2.2.3, at modules/subscriptions/Subscriptions.php

427 lines 15.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace wpforo\modules\subscriptions;
4
5 use stdClass;
6 use wpforo\modules\subscriptions\classes\Template;
7 use wpforo\modules\subscriptions\classes\Actions;
8 use wpforo\modules\mentioning\Mentioning;
9 use wpforo\modules\follows\Follows;
10
11 // Exit if accessed directly
12 if( ! defined( 'ABSPATH' ) ) exit;
13
14 class Subscriptions {
15 public $default;
16 /* @var Template */ public $Template;
17 /* @var Actions */ public $Actions;
18 /* @var Mentioning */ public $Mentioning;
19 /* @var Follows */ public $Follows;
20
21 function __construct() {
22 $this->init_defaults();
23 $this->init_classes();
24 $this->init_hooks();
25 }
26
27 private function init_defaults() {
28 $this->default = new stdClass;
29 $this->default->subscribe_format = [
30 'subid' => '%d',
31 'type' => '%s',
32 'itemid' => '%d',
33 'userid' => '%d',
34 'confirmkey' => '%s',
35 'active' => '%d',
36 'user_name' => '%s',
37 'user_email' => '%s',
38 ];
39 }
40
41 private function init_classes() {
42 $this->Template = new Template();
43 $this->Actions = new Actions();
44 $this->Mentioning = new Mentioning();
45 $this->Follows = new Follows();
46 }
47
48 private function init_hooks() {
49 add_filter( 'wpforo_init_member_templates', [ $this, 'add_templates' ] );
50 add_filter( 'wpforo_after_init_current_object', [ $this, 'init_current_object' ] );
51 }
52
53 public function add_templates( $templates ) {
54 $templates['subscriptions'] = [
55 'type' => 'callback',
56 'key' => 'subscriptions',
57 'menu_shortcode' => 'wpforo-profile-subscriptions',
58 'ico' => '<i class="fas fa-rss"></i>',
59 'title' => 'Subscriptions',
60 'is_default' => 1,
61 'can' => 'vprs',
62 'add_in_member_menu' => 1,
63 'add_in_member_buttons' => 1,
64 'callback_for_page' => function(){
65 require wpftpl( 'profile-subscriptions.php' );
66 },
67 ];
68
69 return $templates;
70 }
71
72 public function init_current_object( $current_object ) {
73 if( !$current_object['is_404'] && $current_object['template'] === 'subscriptions' ){
74 $args = [
75 'offset' => ( $current_object['paged'] - 1 ) * $current_object['items_per_page'],
76 'row_count' => $current_object['items_per_page'],
77 'userid' => $current_object['userid'],
78 'order' => 'DESC',
79 ];
80 $current_object['items_count'] = 0;
81 $current_object['subscribes'] = $this->get_subscribes( $args, $current_object['items_count'] );
82 }
83
84 return $current_object;
85 }
86
87 function get_confirm_key() {
88 return substr( md5( rand() . time() ), 0, 32 );
89 }
90
91 function add( $args = [] ) {
92 if( empty( $args ) && empty( $_REQUEST['sbscrb'] ) ) return false;
93 if( empty( $args ) && ! empty( $_REQUEST['sbscrb'] ) ) $args = $_REQUEST['sbscrb'];
94 if( ! isset( $args['active'] ) || ! $args['active'] ) $args['active'] = 0;
95
96 extract( $args );
97 if( ! isset( $itemid ) || ! ( ( isset( $userid ) && $userid ) || ( isset( $user_email ) && $user_email ) ) || ! isset( $type ) || ! $type ) return false;
98
99 if( empty( $confirmkey ) ) $confirmkey = $this->get_confirm_key();
100
101 $user_name = ( isset( $user_name ) && $user_name ? $user_name : '' );
102 $user_email = ( isset( $user_email ) && $user_email ? $user_email : '' );
103
104 $sql = "SELECT EXISTS(
105 SELECT * FROM `" . WPF()->tables->subscribes . "`
106 WHERE `itemid` = %d
107 AND `type` = %s
108 AND `userid` = %d
109 AND `user_email` = %s
110 ) AS is_exists";
111 $sql = WPF()->db->prepare( $sql, $itemid, $type, $userid, $user_email );
112 if( ! WPF()->db->get_var( $sql ) ) {
113 if( WPF()->db->insert(
114 WPF()->tables->subscribes,
115 [
116 'itemid' => $itemid,
117 'type' => $type,
118 'confirmkey' => $confirmkey,
119 'userid' => $userid,
120 'active' => $active,
121 'user_name' => $user_name,
122 'user_email' => $user_email,
123 ],
124 [ '%d', '%s', '%s', '%d', '%d', '%s', '%s' ]
125 ) ) {
126 if( isset( $active ) && $active == 1 ) {
127 if( intval( $userid ) === WPF()->current_userid ) {
128 WPF()->notice->add( 'You have been successfully subscribed', 'success' );
129 } else {
130 WPF()->notice->add( 'Success!', 'success' );
131 }
132 } else {
133 if( intval( $userid ) === WPF()->current_userid ) {
134 WPF()->notice->add( 'Success! Thank you. Please check your email and click confirmation link below to complete this step.', 'success' );
135 } else {
136 WPF()->notice->add( 'Success!', 'success' );
137 }
138 }
139
140 return $confirmkey;
141 }
142
143 }
144
145 WPF()->notice->add( 'Can\'t subscribe to this item', 'error' );
146
147 return false;
148 }
149
150 function edit( $confirmkey = '' ) {
151 if( ! $confirmkey && isset( $_REQUEST['key'] ) && $_REQUEST['key'] ) $confirmkey = $_REQUEST['key'];
152 if( ! $confirmkey ) {
153 WPF()->notice->add( 'Invalid request!', 'error' );
154 return false;
155 }
156
157 if( WPF()->db->update( WPF()->tables->subscribes, [ 'active' => 1 ], [ 'confirmkey' => sanitize_text_field( $confirmkey ) ], [ '%d' ], [ '%s' ] ) ) {
158 if( $sbs = $this->get_subscribe( $confirmkey ) ) WPF()->member->set_is_email_confirmed( $sbs['userid'], 1 );
159
160 WPF()->notice->add( 'You have been successfully subscribed', 'success' );
161 return true;
162 }
163
164 WPF()->notice->add( 'Your subscription for this item could not be confirmed', 'error' );
165 return false;
166 }
167
168 public function reset( $data = [], $all = '', $user = null ) {
169 if( ! $user && ! WPF()->current_userid && ! WPF()->current_user_email ) return false;
170 if( ! $user ) $user = ( WPF()->current_userid ? WPF()->current_userid : WPF()->current_user_email );
171 $data = array_filter( (array) $data );
172 $args = [
173 'itemid' => 0,
174 'type' => '',
175 'userid' => 0,
176 'active' => ( wpforo_setting( 'subscriptions', 'subscribe_confirmation' ) ? 0 : 1 ),
177 'user_name' => '',
178 'user_email' => '',
179 ];
180 if( is_numeric( $user ) ) {
181 $args['userid'] = $user;
182 $where = WPF()->db->prepare( "`userid` = %d", $user );
183 } else {
184 $args['user_email'] = $user;
185 $args['user_name'] = WPF()->current_user_display_name;
186 $where = WPF()->db->prepare( "`user_email` = %s", $user );
187 }
188
189 if( $args['active'] !== 1 && $this->is_email_confirmed( $user ) ) $args['active'] = 1;
190
191 $types = [ 'forum', 'forum-topic' ];
192 if( ! $all ) array_push( $types, 'forums', 'forums-topics' );
193 $sql = "DELETE FROM `" . WPF()->tables->subscribes . "` WHERE `type` IN('" . implode( "','", $types ) . "') AND " . $where;
194 if( ! $all && $data ) {
195 $forumids = array_keys( $data );
196 $sql .= " AND `itemid` NOT IN(" . implode( ',', $forumids ) . ")";
197 }
198 WPF()->db->query( $sql );
199
200 if( ! $all && $data ) {
201 foreach( $data as $forumid => $type ) {
202 $sql = "SELECT `subid` FROM `" . WPF()->tables->subscribes . "` WHERE `type` IN('forum', 'forum-topic') AND `itemid` = %d AND " . $where;
203 $sql = WPF()->db->prepare( $sql, $forumid );
204 if( $subid = WPF()->db->get_var( $sql ) ) {
205 WPF()->db->update( WPF()->tables->subscribes, [ 'type' => sanitize_text_field( $type ), 'active' => $args['active'] ], [ 'subid' => $subid ], [ '%s', '%d' ], [ '%d' ] );
206 } else {
207 $args['itemid'] = intval( $forumid );
208 $args['type'] = sanitize_text_field( $type );
209 $this->add( $args );
210 }
211 }
212 }
213
214 if( $all ) {
215 $sql = "SELECT `subid` FROM `" . WPF()->tables->subscribes . "` WHERE `type` IN('forums', 'forums-topics') AND `itemid` = 0 AND " . $where;
216 if( $subid = WPF()->db->get_var( $sql ) ) {
217 WPF()->db->update( WPF()->tables->subscribes, [ 'type' => sanitize_text_field( $all ), 'active' => $args['active'] ], [ 'subid' => $subid ], [ '%s', '%d' ], [ '%d' ] );
218 } else {
219 $args['itemid'] = 0;
220 $args['type'] = sanitize_text_field( $all );
221 $this->add( $args );
222 }
223 }
224
225 return true;
226 }
227
228 function delete( $where = [], $table = '' ) {
229 if( ! $where && $confirmkey = wpfval( $_REQUEST, 'confirmkey' ) ) $where = $confirmkey;
230 if( ! $where ) {
231 WPF()->notice->add( 'Invalid request!', 'error' );
232 return false;
233 }
234
235 if( ! is_array( $where ) ) $where = [ 'confirmkey' => $where ];
236 $where = (array) $where;
237
238 $where = wpforo_array_ordered_intersect_key( $where, $this->default->subscribe_format );
239 if( false !== WPF()->db->delete(
240 $table ?: WPF()->tables->subscribes,
241 $where,
242 wpforo_array_ordered_intersect_key( $this->default->subscribe_format, $where )
243 ) ) {
244 WPF()->notice->add( 'You have been successfully unsubscribed', 'success' );
245 return true;
246 }
247
248 WPF()->notice->add( 'Could not be unsubscribe from this item', 'error' );
249 return false;
250 }
251
252 public function delete_for_all_active_boards( $where = [] ) {
253 if ( $boardids = WPF()->board->get_active_boardids() ) {
254 foreach ( $boardids as $boardid ) {
255 WPF()->change_board( $boardid );
256 $this->delete( $where );
257 }
258 }
259 }
260
261 /**
262 * @param $args array|string
263 * @param $operator string
264 *
265 * @return array
266 */
267 function get_subscribe( $args, $operator = 'AND' ) {
268 if( is_string( $args ) ) $args = [ "confirmkey" => sanitize_text_field( $args ) ];
269
270 $operator = strtoupper( (string) $operator );
271 if( ! in_array( $operator, [ 'AND', 'OR' ], true ) ) $operator = 'AND';
272
273 $default = [
274 'subid' => null,
275 'itemid' => null,
276 'type' => null,
277 'confirmkey' => null,
278 'userid' => null,
279 'user_email' => null,
280 'active' => null,
281 'order' => '`subid` DESC',
282 'offset' => null,
283 'row_count' => null,
284 ];
285
286 $args = array_merge( $default, $args );
287
288 $sql = "SELECT * FROM `" . WPF()->tables->subscribes . "`";
289
290 $wheres = [];
291 if( ! is_null( $args['subid'] ) ) $wheres[] = "`subid` = " . wpforo_bigintval( $args['subid'] );
292 if( ! is_null( $args['itemid'] ) ) $wheres[] = "`itemid` = " . wpforo_bigintval( $args['itemid'] );
293 if( ! is_null( $args['userid'] ) ) $wheres[] = "`userid` = " . wpforo_bigintval( $args['userid'] );
294 if( ! wpforo_bigintval( $args['userid'] )
295 && ! is_null( $args['user_email'] ) ) $wheres[] = "`user_email` = '" . esc_sql( $args['user_email'] ) . "'";
296 if( ! is_null( $args['confirmkey'] ) ) $wheres[] = "`confirmkey` = '" . esc_sql( $args['confirmkey'] ) . "'";
297 if( ! is_null( $args['active'] ) ) $wheres[] = "`active` = " . intval( $args['active'] );
298 if( ! is_null( $args['type'] ) ) $wheres[] = "`type` IN( '" . implode( "','", array_map( 'esc_sql', (array) $args['type'] ) ) . "' )";
299
300 if( $wheres ) $sql .= sprintf( ' WHERE %1$s', implode( sprintf(' %1$s ', $operator), $wheres ) );
301 if( (int) $args['row_count'] ) $sql .= sprintf( ' LIMIT %1$d,%2$d', intval( $args['offset'] ), intval( $args['row_count'] ) );
302
303 if( WPF()->ram_cache->exists( $sql ) ) {
304 $subscribe = WPF()->ram_cache->get( $sql );
305 } else {
306 $subscribe = (array) WPF()->db->get_row( $sql, ARRAY_A );
307 WPF()->ram_cache->set( $sql, $subscribe );
308 }
309
310 return $subscribe;
311 }
312
313 function get_subscribes( $args = [], &$items_count = 0 ) {
314 $default = [
315 'itemid' => null,
316 'type' => [], // topic | forum
317 'userid' => null, //
318 'active' => 1,
319 'orderby' => 'subid', // order by `field`
320 'order' => 'DESC', // ASC DESC
321 'offset' => null, // OFFSET
322 'row_count' => null, // ROW COUNT
323 ];
324
325 $args = wpforo_parse_args( $args, $default );
326 extract( $args );
327
328 $sql = "SELECT * FROM `" . WPF()->tables->subscribes . "`";
329 $wheres = [];
330
331 if( $type ) $wheres[] = " `type` IN( '" . implode( "','", array_map( 'esc_sql', (array) $type ) ) . "')";
332 if( ! is_null( $active ) ) $wheres[] = " `active` = " . intval( $active );
333 if( ! is_null( $itemid ) ) $wheres[] = " `itemid` = " . wpforo_bigintval( $itemid );
334 if( ! is_null( $userid ) ) $wheres[] = " `userid` = " . wpforo_bigintval( $userid );
335
336 if( ! empty( $wheres ) ) $sql .= " WHERE " . implode( " AND ", $wheres );
337
338 $item_count_sql = preg_replace( '#SELECT.+?FROM#isu', 'SELECT count(*) FROM', $sql );
339 if( $item_count_sql ) $items_count = WPF()->db->get_var( $item_count_sql );
340
341 $sql .= " ORDER BY `$orderby` " . $order;
342
343 if( ! is_null( $row_count ) ) {
344 if( ! is_null( $offset ) ) {
345 $sql .= esc_sql( " LIMIT $offset,$row_count" );
346 } else {
347 $sql .= esc_sql( " LIMIT $row_count" );
348 }
349 }
350
351 return WPF()->db->get_results( $sql, ARRAY_A );
352
353 }
354
355 function get_confirm_link( $args ) {
356 if( is_string( $args ) ) return wpforo_home_url( "?wpfaction=sbscrbconfirm&key=" . sanitize_text_field( $args ) );
357
358 if( $args['type'] === 'forum' ) {
359 $url = WPF()->forum->get_forum_url( $args['itemid'] ) . '/';
360 } elseif( $args['type'] === 'topic' ) {
361 $url = WPF()->topic->get_url( $args['itemid'] ) . '/';
362 } else {
363 $url = wpforo_home_url();
364 }
365
366 return wpforo_home_url( $url . "?wpfaction=sbscrbconfirm&key=" . sanitize_text_field( $args['confirmkey'] ) );
367 }
368
369 function get_unsubscribe_link( $confirmkey ) {
370 return wpforo_home_url( "?wpfaction=unsbscrb&key=" . sanitize_text_field( $confirmkey ) );
371 }
372
373 public function is_email_confirmed( $user = null ) {
374 if( ! $user && ! WPF()->current_userid && ! WPF()->current_user_email ) return false;
375 if( ! $user ) $user = ( WPF()->current_userid ? WPF()->current_userid : WPF()->current_user_email );
376
377 $sql = ( is_numeric( $user ) ? "`userid` = %d" : "`user_email` = %s" );
378 $where = WPF()->db->prepare( $sql, $user );
379
380 if( WPF()->current_userid === $user && wpfval( WPF()->current_user, 'is_email_confirmed' ) ) {
381 $has_confirmed = WPF()->current_user['is_email_confirmed'];
382 } elseif( is_numeric( $user ) ) {
383 $has_confirmed = WPF()->member->get_is_email_confirmed( WPF()->current_userid );
384 } else {
385 $has_confirmed = WPF()->db->get_var( "SELECT `subid` FROM `" . WPF()->tables->subscribes . "` WHERE `active` = 1 AND " . $where );
386 }
387
388 return (bool) $has_confirmed;
389 }
390
391 public function get_sbj_msg( $type, $pitem, $item, $owner, $user, $unsubscribe_link ){
392 $sbj = '';
393 $msg = '';
394 switch( $type ){
395 case 'new_topic':
396 $sbj = wpforo_setting( 'subscriptions', 'new_topic_notification_email_subject' );
397 $msg = wpforo_setting( 'subscriptions', 'new_topic_notification_email_message' );
398 if( (int) $item['status'] ) {
399 $sbj = __( 'Please Moderate: ', 'wpforo' ) . $sbj;
400 $msg .= sprintf( '<br><br><p style="color: #DD0000;">%1$s</p>', __( 'This topic is currently unapproved. You can approve topics in Dashboard &raquo; Forums &raquo; Moderation admin page.', 'wpforo' ) );
401 }
402 break;
403 case 'new_post':
404 $sbj = wpforo_setting( 'subscriptions', 'new_post_notification_email_subject' );
405 $msg = wpforo_setting( 'subscriptions', 'new_post_notification_email_message' );
406 if( (int) $item['status'] ) {
407 $sbj = __( 'Please Moderate: ', 'wpforo' ) . $sbj;
408 $msg .= sprintf( '<br><br><p style="color: #DD0000;">%1$s</p>', __( 'This post is currently unapproved. You can approve posts in Dashboard &raquo; Forums &raquo; Moderation admin page.', 'wpforo' ) );
409 }
410 break;
411 case 'user_follow';
412 $sbj = wpforo_setting( 'subscriptions', 'user_following_email_subject' );
413 $msg = wpforo_setting( 'subscriptions', 'user_following_email_message' );
414 break;
415 case 'user_mention';
416 $sbj = wpforo_setting( 'subscriptions', 'user_mention_email_subject' );
417 $msg = wpforo_setting( 'subscriptions', 'user_mention_email_message' );
418 break;
419 }
420
421 $sbj = wpforo_apply_email_shortcodes( $sbj, $pitem, $item, $owner, $user, $unsubscribe_link );
422 $msg = wpforo_apply_email_shortcodes( $msg, $pitem, $item, $owner, $user, $unsubscribe_link );
423
424 return compact( 'sbj', 'msg' );
425 }
426 }
427