user_login(); } } return false; } /** * clear_posts_cache * * @return void */ public function clear_posts_cache() { global $system, $db; $db->query(sprintf("DELETE FROM posts_cache WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); if ($db->affected_rows > 0) { return true; } return false; } /* ------------------------------- */ /* Posts Actions */ /* ------------------------------- */ /** * share * * @param integer $post_id * @param array $args *@return void */ public function share($post_id, $args) { global $db, $date; /* check if the viewer can share the post */ $post = $this->_check_post($post_id, true); if (!$post) { _error(403); } if ($post['privacy'] != 'public' && !($post['in_group'] && $post['group_privacy'] == "public") && !($post['in_event'] && $post['event_privacy'] == "public")) { _error(403); } /* check blocking */ if ($post['user_type'] == "user" && $this->blocked($post['author_id'])) { _error(403); } // share post /* get the origin post */ if ($post['post_type'] == "shared") { $origin = $this->_check_post($post['origin_id'], true); if (!$origin) { _error(403); } if ($origin['privacy'] != 'public' && !($origin['in_group'] && $origin['group_privacy'] == "public") && !($origin['in_event'] && $origin['event_privacy'] == "public")) { _error(403); } $post_id = $origin['post_id']; $author_id = $origin['author_id']; } else { $post_id = $post['post_id']; $author_id = $post['author_id']; } /* share to */ switch ($args['share_to']) { case 'timeline': /* insert the new shared post */ $db->query(sprintf("INSERT INTO posts (user_id, user_type, post_type, origin_id, time, privacy, text) VALUES (%s, 'user', 'shared', %s, %s, 'public', %s)", secure($this->_data['user_id'], 'int'), secure($post_id, 'int'), secure($date), secure($args['message']))); break; case 'page': /* check if the page is valid */ $check_page = $db->query(sprintf("SELECT COUNT(*) as count FROM pages WHERE page_id = %s", secure($args['page'], 'int'))); if ($check_page->fetch_assoc()['count'] == 0) { _error(400); } /* check if the viewer is page admin */ if (!$this->check_page_adminship($this->_data['user_id'], $args['page'])) { _error(400); } /* insert the new shared post */ $db->query(sprintf("INSERT INTO posts (user_id, user_type, post_type, origin_id, time, privacy, text) VALUES (%s, 'page', 'shared', %s, %s, 'public', %s)", secure($args['page'], 'int'), secure($post_id, 'int'), secure($date), secure($args['message']))); break; case 'group': /* check if the group is valid */ $get_group = $db->query(sprintf("SELECT * FROM `groups` WHERE group_id = %s", secure($args['group'], 'int'))); if ($get_group->num_rows == 0) { _error(400); } $group = $get_group->fetch_assoc(); /* check if the viewer is group member */ if ($this->check_group_membership($this->_data['user_id'], $args['group']) != "approved") { _error(400); } /* check if user is a group admin */ $group['i_admin'] = $this->check_group_adminship($this->_data['user_id'], $group['group_id']); /* check if group publishing enabled */ if (!$group['group_publish_enabled'] && !$group['i_admin']) { throw new Exception(__("Publishing to this group has been disabled by group admins")); } /* insert the new shared post */ $group_approved = ($group['group_publish_approval_enabled'] && !$group['i_admin']) ? "0" : "1"; $db->query(sprintf("INSERT INTO posts (user_id, user_type, post_type, origin_id, time, privacy, text, in_group, group_id, group_approved) VALUES (%s, 'user', 'shared', %s, %s, 'custom', %s, '1', %s, %s)", secure($this->_data['user_id'], 'int'), secure($post_id, 'int'), secure($date), secure($args['message']), secure($args['group'], 'int'), secure($group_approved))); $post_id = $db->insert_id; /* post in_group notification */ if (!$group_approved) { /* send notification to group admin */ $this->post_notification(['to_user_id' => $group['group_admin'], 'action' => 'group_post_pending', 'node_type' => $group['group_title'], 'node_url' => $group['group_name'] . "-[guid=]" . $post_id]); } break; case 'event': /* check if the event is valid */ $get_event = $db->query(sprintf("SELECT * FROM `events` WHERE event_id = %s", secure($args['event'], 'int'))); if ($get_event->num_rows == 0) { _error(400); } $event = $get_event->fetch_assoc(); /* check if the viewer is event member */ if (!$this->check_event_membership($this->_data['user_id'], $args['event'])) { _error(400); } /* check if user is a event admin */ $event['i_admin'] = $this->check_event_adminship($this->_data['user_id'], $event['event_id']); /* check if event publishing enabled */ if (!$event['event_publish_enabled'] && !$event['i_admin']) { throw new Exception(__("Publishing to this event has been disabled by event admins")); } /* insert the new shared post */ $event_approved = ($event['event_publish_approval_enabled'] && !$event['i_admin']) ? "0" : "1"; $db->query(sprintf("INSERT INTO posts (user_id, user_type, post_type, origin_id, time, privacy, text, in_event, event_id, event_approved) VALUES (%s, 'user', 'shared', %s, %s, 'custom', %s, '1', %s, %s)", secure($this->_data['user_id'], 'int'), secure($post_id, 'int'), secure($date), secure($args['message']), secure($args['event'], 'int'), secure($event_approved))); $post_id = $db->insert_id; /* post in_event notification */ if (!$event_approved) { /* send notification to event admin */ $this->post_notification(['to_user_id' => $event['event_admin'], 'action' => 'event_post_pending', 'node_type' => $event['event_title'], 'node_url' => $event['event_name'] . "-[guid=]" . $post_id]); } break; default: _error(403); break; } /* update the origin post shares counter */ $db->query(sprintf("UPDATE posts SET shares = shares + 1 WHERE post_id = %s", secure($post_id, 'int'))); /* post notification */ $this->post_notification(['to_user_id' => $author_id, 'action' => 'share', 'node_type' => 'post', 'node_url' => $post_id]); } /** * delete_posts * * @param integer $node_id * @param string $node_type * @return void */ public function delete_posts($node_id, $node_type = 'user') { global $db; /* get all user posts */ switch ($node_type) { case 'user': $get_posts = $db->query(sprintf("SELECT post_id FROM posts WHERE user_id = %s AND user_type = 'user'", secure($node_id, 'int'))); break; case 'page': $get_posts = $db->query(sprintf("SELECT post_id FROM posts WHERE user_id = %s AND user_type = 'page'", secure($node_id, 'int'))); break; case 'group': $get_posts = $db->query(sprintf("SELECT post_id FROM posts WHERE group_id = %s AND in_group = '1'", secure($node_id, 'int'))); break; case 'event': $get_posts = $db->query(sprintf("SELECT post_id FROM posts WHERE event_id = %s AND in_event = '1'", secure($node_id, 'int'))); break; } if ($get_posts->num_rows > 0) { while ($post = $get_posts->fetch_assoc()) { $this->delete_post($post['post_id'], false); } } } /** * delete_post * * @param integer $post_id * @param boolean $return_errors * @return boolean */ public function delete_post($post_id, $return_errors = true) { global $db, $system; /* (check|get) post */ $post = $this->get_post($post_id, false, true); if (!$post) { if (!$return_errors) { return; } _error(403); } /* can delete the post */ if (!$post['manage_post']) { if (!$return_errors) { return; } /* check & delete orphaned data */ if ($this->_is_admin) { $check_post = $db->query(sprintf("SELECT COUNT(*) as count FROM posts WHERE post_id = %s", secure($post_id, 'int'))); if ($check_post->fetch_assoc()['count'] > 0) { $db->query(sprintf("DELETE FROM posts WHERE post_id = %s", secure($post_id, 'int'))); return; } } _error(403); } /* delete hashtags */ $this->delete_hashtags($post_id); /* delete post comments */ $get_comments = $db->query(sprintf("SELECT posts_comments.comment_id FROM posts_comments WHERE node_id = %s AND node_type = 'post'", secure($post_id, 'int'))) or _error("SQL_ERROR_THROWEN"); if ($get_comments->num_rows > 0) { while ($comment = $get_comments->fetch_assoc()) { $this->delete_comment($comment['comment_id']); } } /* set refresh */ $refresh = false; /* delete post */ $db->query(sprintf("DELETE FROM posts WHERE post_id = %s", secure($post_id, 'int'))); /* delete post hidden */ $db->query(sprintf("DELETE FROM posts_hidden WHERE post_id = %s", secure($post_id, 'int'))); /* delete post paid */ $db->query(sprintf("DELETE FROM posts_paid WHERE post_id = %s", secure($post_id, 'int'))); /* delete posts reactions */ $db->query(sprintf("DELETE FROM posts_reactions WHERE post_id = %s", secure($post_id, 'int'))); /* delete posts saved */ $db->query(sprintf("DELETE FROM posts_saved WHERE post_id = %s", secure($post_id, 'int'))); /* delete reports */ $db->query(sprintf("DELETE FROM reports WHERE node_type = 'post' AND node_id = %s", secure($post_id, 'int'))); /* delete subscriptions image if exists */ if ($post['for_subscriptions'] && $post['subscription_image']) { delete_uploads_file($post['subscription_image']); } /* delete paid image if exists */ if ($post['is_paid'] && $post['paid_image']) { delete_uploads_file($post['paid_image']); } /* delete nested tables */ /* delete photos post */ if (in_array($post['post_type'], ['photos', 'album', 'profile_cover', 'profile_picture', 'page_cover', 'page_picture', 'group_cover', 'group_picture', 'event_cover', 'product', 'combo']) && $post['photos']) { /* delete post photos from database */ $db->query(sprintf("DELETE FROM posts_photos WHERE post_id = %s", secure($post_id, 'int'))); switch ($post['post_type']) { case 'profile_cover': /* update user cover if it's current cover */ if ($post['user_cover_id'] == $post['photos'][0]['photo_id']) { $db->query(sprintf("UPDATE users SET user_cover = null, user_cover_id = null WHERE user_id = %s", secure($post['author_id'], 'int'))); /* return */ $refresh = true; } break; case 'profile_picture': /* update user picture if it's current picture */ if ($post['user_picture_id'] == $post['photos'][0]['photo_id']) { $db->query(sprintf("UPDATE users SET user_picture = null, user_picture_id = null WHERE user_id = %s", secure($post['author_id'], 'int'))); /* delete cropped picture from uploads folder */ delete_uploads_file($post['user_picture']); /* return */ $refresh = true; } break; case 'page_cover': /* update page cover if it's current cover */ if ($post['page_cover_id'] == $post['photos'][0]['photo_id']) { $db->query(sprintf("UPDATE pages SET page_cover = null, page_cover_id = null WHERE page_id = %s", secure($post['user_id'], 'int'))); /* return */ $refresh = true; } break; case 'page_picture': /* update page picture if it's current picture */ if ($post['page_picture_id'] == $post['photos'][0]['photo_id']) { $db->query(sprintf("UPDATE pages SET page_picture = null, page_picture_id = null WHERE page_id = %s", secure($post['user_id'], 'int'))); /* delete cropped picture from uploads folder */ delete_uploads_file($post['page_picture']); /* return */ $refresh = true; } break; case 'group_cover': /* update group cover if it's current cover */ if ($post['group_cover_id'] == $post['photos'][0]['photo_id']) { $db->query(sprintf("UPDATE `groups` SET group_cover = null, group_cover_id = null WHERE group_id = %s", secure($post['group_id'], 'int'))); /* return */ $refresh = true; } break; case 'group_picture': /* update group picture if it's current picture */ if ($post['group_picture_id'] == $post['photos'][0]['photo_id']) { $db->query(sprintf("UPDATE `groups` SET group_picture = null, group_picture_id = null WHERE group_id = %s", secure($post['group_id'], 'int'))); /* delete cropped from uploads folder */ delete_uploads_file($post['group_picture']); /* return */ $refresh = true; } break; case 'event_cover': /* update event cover if it's current cover */ if ($post['event_cover_id'] == $post['photos'][0]['photo_id']) { $db->query(sprintf("UPDATE `events` SET event_cover = null, event_cover_id = null WHERE event_id = %s", secure($post['event_id'], 'int'))); /* return */ $refresh = true; } break; case 'product': /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_products WHERE post_id = %s", secure($post_id, 'int'))); break; } /* delete uploads from uploads folder */ foreach ($post['photos'] as $photo) { delete_uploads_file($photo['source']); } } /* delete media post */ if ($post['post_type'] == 'media') { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_media WHERE post_id = %s", secure($post_id, 'int'))); } /* delete link post */ if ($post['post_type'] == 'link') { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_links WHERE post_id = %s", secure($post_id, 'int'))); } /* delete live post */ if ($post['post_type'] == 'live') { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_live WHERE post_id = %s", secure($post_id, 'int'))); /* delete live users */ $db->query(sprintf("DELETE FROM posts_live_users WHERE post_id = %s", secure($post_id, 'int'))); } /* delete blog post */ if ($post['post_type'] == 'article') { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_articles WHERE post_id = %s", secure($post_id, 'int'))); /* delete uploads from uploads folder */ delete_uploads_file($post['blog']['cover']); } /* delete funding post */ if ($post['post_type'] == 'funding') { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_funding WHERE post_id = %s", secure($post_id, 'int'))); /* delete funding donors */ $db->query(sprintf("DELETE FROM posts_funding_donors WHERE post_id = %s", secure($post_id, 'int'))); } /* delete offer post */ if ($post['post_type'] == 'offer') { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_offers WHERE post_id = %s", secure($post_id, 'int'))); /* delete uploads from uploads folder */ delete_uploads_file($post['offer']['thumbnail']); } /* delete job post */ if ($post['post_type'] == 'job') { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_jobs WHERE post_id = %s", secure($post_id, 'int'))); /* delete uploads from uploads folder */ delete_uploads_file($post['job']['cover_image']); } /* delete course post */ if ($post['post_type'] == 'course') { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_courses WHERE post_id = %s", secure($post_id, 'int'))); /* delete uploads from uploads folder */ delete_uploads_file($post['course']['cover_image']); } /* delete poll post */ if ($post['post_type'] == 'poll') { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_polls WHERE post_id = %s", secure($post_id, 'int'))); $db->query(sprintf("DELETE FROM posts_polls_options WHERE poll_id = %s", secure($post['poll']['poll_id'], 'int'))); $db->query(sprintf("DELETE FROM posts_polls_options_users WHERE poll_id = %s", secure($post['poll']['poll_id'], 'int'))); } /* delete reel post */ if ($post['post_type'] == 'reel' && $post['reel']) { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_reels WHERE post_id = %s", secure($post_id, 'int'))); /* delete uploads from uploads folder */ delete_uploads_file($post['reel']['thumbnail']); delete_uploads_file($post['reel']['source']); delete_uploads_file($post['reel']['source_240p']); delete_uploads_file($post['reel']['source_360p']); delete_uploads_file($post['reel']['source_480p']); delete_uploads_file($post['reel']['source_720p']); delete_uploads_file($post['reel']['source_1080p']); delete_uploads_file($post['reel']['source_1440p']); delete_uploads_file($post['reel']['source_2160p']); } /* delete video post */ if (($post['post_type'] == 'video' || $post['post_type'] == 'combo') && $post['video']) { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_videos WHERE post_id = %s", secure($post_id, 'int'))); /* delete uploads from uploads folder */ delete_uploads_file($post['video']['thumbnail']); delete_uploads_file($post['video']['source']); delete_uploads_file($post['video']['source_240p']); delete_uploads_file($post['video']['source_360p']); delete_uploads_file($post['video']['source_480p']); delete_uploads_file($post['video']['source_720p']); delete_uploads_file($post['video']['source_1080p']); delete_uploads_file($post['video']['source_1440p']); delete_uploads_file($post['video']['source_2160p']); } /* delete audio post */ if (($post['post_type'] == 'audio' || $post['post_type'] == 'combo') && $post['audio']) { /* delete uploads from uploads folder */ delete_uploads_file($post['audio']['source']); /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_audios WHERE post_id = %s", secure($post_id, 'int'))); } /* delete file post */ if (($post['post_type'] == 'file' || $post['post_type'] == 'combo') && $post['file']) { /* delete nested table row */ $db->query(sprintf("DELETE FROM posts_files WHERE post_id = %s", secure($post_id, 'int'))); /* delete uploads from uploads folder */ delete_uploads_file($post['file']['source']); } /* points balance */ $this->points_balance("delete", $post['author_id'], "post"); /* delete post in_group notification */ if ($post['in_group'] && !$post['group_approved']) { $this->delete_notification($post['group_admin'], 'group_post_pending', $post['group_title'], $post['group_name'] . "-[guid=]" . $post['post_id']); } /* delete post in_event notification */ if ($post['in_event'] && !$post['event_approved']) { $this->delete_notification($post['event_admin'], 'event_post_pending', $post['event_title'], $post['event_id'] . "-[guid=]" . $post['post_id']); } return $refresh; } /** * edit_post * * @param integer $post_id * @param string $message * @return array */ public function edit_post($post_id, $message) { global $db, $system; /* (check|get) post */ $post = $this->_check_post($post_id, true); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* check post max length */ if ($system['max_post_length'] > 0 && $this->_data['user_group'] >= 3) { if (strlen($message) >= $system['max_post_length']) { modal("MESSAGE", __("Text Length Limit Reached"), __("Your message characters length is over the allowed limit") . " (" . $system['max_post_length'] . " " . __("Characters") . ")"); } } /* delete hashtags */ $this->delete_hashtags($post_id); /* check if post in_group with approval system */ if ($post['in_group'] && $post['group_publish_approval_enabled'] && $post['group_approved']) { $post['group_approved'] = ($post['group_publish_approval_enabled'] && !$post['is_group_admin']) ? '0' : '1'; /* post notification to group admin */ if (!$post['group_approved']) { $this->post_notification(['to_user_id' => $post['group_admin'], 'action' => 'group_post_pending', 'node_type' => $post['group_title'], 'node_url' => $post['group_name'] . "-[guid=]" . $post['post_id']]); } } /* check if post in_event with approval system */ if ($post['in_event'] && $post['event_publish_approval_enabled'] && $post['event_approved']) { $post['event_approved'] = ($post['event_publish_approval_enabled'] && !$post['is_event_admin']) ? '0' : '1'; /* post notification to event admin */ if (!$post['event_approved']) { $this->post_notification(['to_user_id' => $post['event_admin'], 'action' => 'event_post_pending', 'node_type' => $post['event_title'], 'node_url' => $post['event_id'] . "-[guid=]" . $post['post_id']]); } } /* update post */ $db->query(sprintf("UPDATE posts SET text = %s, group_approved = %s, event_approved = %s WHERE post_id = %s", secure($message), secure($post['group_approved']), secure($post['event_approved']), secure($post_id, 'int'))); /* post mention notifications */ $this->post_mentions($message, $post_id); /* parse text */ $post['text_plain'] = htmlentities($message, ENT_QUOTES, 'utf-8'); $post['text'] = $this->_parse(["text" => $post['text_plain'], "trending_hashtags" => true, "post_id" => $post_id]); /* get post colored pattern */ $post['colored_pattern'] = $this->get_posts_colored_pattern($post['colored_pattern']); /* return */ return $post; } /** * edit_product * * @param integer $post_id * @param string $message * @param array $args * @return void */ public function edit_product($post_id, $message, $args = []) { global $db, $system; /* (check|get) post */ $post = $this->_check_post($post_id, true); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* update post */ $db->query(sprintf("UPDATE posts SET text = %s WHERE post_id = %s", secure($message), secure($post_id, 'int'))); /* update product */ $db->query(sprintf("UPDATE posts_products SET name = %s, price = %s, quantity = %s, category_id = %s, status = %s, location = %s, is_digital = %s, product_download_url = %s, product_file_source = %s WHERE post_id = %s", secure($args['name']), secure($args['price'], 'float'), secure($args['quantity'], 'int'), secure($args['category'], 'int'), secure($args['status']), secure($args['location']), secure($args['is_digital']), secure($args['product_url']), secure($args['product_file']), secure($post_id, 'int'))); } /** * edit_funding * * @param integer $post_id * @param string $message * @param array $args * @return void */ public function edit_funding($post_id, $message, $args = []) { global $db, $system; /* (check|get) post */ $post = $this->_check_post($post_id, true); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* update post */ $db->query(sprintf("UPDATE posts SET text = %s WHERE post_id = %s", secure($message), secure($post_id, 'int'))); /* update funding */ $db->query(sprintf("UPDATE posts_funding SET title = %s, amount = %s, cover_image = %s WHERE post_id = %s", secure($args['title']), secure($args['amount']), secure($args['cover_image']), secure($post_id, 'int'))); } /** * edit_offer * * @param integer $post_id * @param string $message * @param array $args * @return void */ public function edit_offer($post_id, $message, $args = []) { global $db, $system; /* (check|get) post */ $post = $this->_check_post($post_id, true); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* prepare end date (optional) */ $end_date = ($args['end_date']) ? secure($args['end_date'], 'datetime') : 'NULL'; /* update post */ $db->query(sprintf("UPDATE posts SET text = %s WHERE post_id = %s", secure($message), secure($post_id, 'int'))); /* update offer */ $db->query(sprintf("UPDATE posts_offers SET category_id = %s, title = %s, discount_type = %s, discount_percent = %s, discount_amount = %s, buy_x = %s, get_y = %s, spend_x = %s, amount_y = %s, end_date = %s, thumbnail = %s, price = %s WHERE post_id = %s", secure($args['category'], 'int'), secure($args['title']), secure($args['discount_type']), secure($args['discount_percent'], 'int'), secure($args['discount_amount']), secure($args['buy_x']), secure($args['get_y']), secure($args['spend_x']), secure($args['amount_y']), $end_date, secure($args['thumbnail']), secure($args['price'], 'float'), secure($post_id, 'int'))); } /** * edit_job * * @param integer $post_id * @param string $message * @param array $arg * @return void */ public function edit_job($post_id, $message, $args = []) { global $db, $system; /* (check|get) post */ $post = $this->_check_post($post_id, true); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* update post */ $db->query(sprintf("UPDATE posts SET text = %s WHERE post_id = %s", secure($message), secure($post_id, 'int'))); /* update job */ $db->query(sprintf( "UPDATE posts_jobs SET category_id = %s, title = %s, location = %s, salary_minimum = %s, salary_minimum_currency = %s, salary_maximum = %s, salary_maximum_currency = %s, pay_salary_per = %s, type = %s, question_1_type = %s, question_1_title = %s, question_1_choices = %s, question_2_type = %s, question_2_title = %s, question_2_choices = %s, question_3_type = %s, question_3_title = %s, question_3_choices = %s, cover_image = %s WHERE post_id = %s", secure($args['category'], 'int'), secure($args['title']), secure($args['location']), secure($args['salary_minimum']), secure($args['salary_minimum_currency'], 'int'), secure($args['salary_maximum']), secure($args['salary_maximum_currency'], 'int'), secure($args['pay_salary_per']), secure($args['type']), secure($args['question_1_type']), secure($args['question_1_title']), secure($args['question_1_choices']), secure($args['question_2_type']), secure($args['question_2_title']), secure($args['question_2_choices']), secure($args['question_3_type']), secure($args['question_3_title']), secure($args['question_3_choices']), secure($args['cover_image']), secure($post_id, 'int') )); } /** * edit_course * * @param integer $post_id * @param string $message * @param array $arg * @return void */ public function edit_course($post_id, $message, $args = []) { global $db, $system; /* (check|get) post */ $post = $this->_check_post($post_id, true); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* update post */ $db->query(sprintf("UPDATE posts SET text = %s WHERE post_id = %s", secure($message), secure($post_id, 'int'))); /* update course */ $db->query(sprintf( "UPDATE posts_courses SET category_id = %s, title = %s, location = %s, fees = %s, fees_currency = %s, start_date = %s, end_date = %s, cover_image = %s WHERE post_id = %s", secure($args['category'], 'int'), secure($args['title']), secure($args['location']), secure($args['fees']), secure($args['fees_currency'], 'int'), secure($args['start_date'], 'datetime'), secure($args['end_date'], 'datetime'), secure($args['cover_image']), secure($post_id, 'int') )); } /** * edit_privacy * * @param integer $post_id * @param string $privacy * @return void */ public function edit_privacy($post_id, $privacy) { global $db, $system; /* (check|get) post */ $post = $this->_check_post($post_id, true); if (!$post) { _error(403); } /* check post type */ if ($post['is_anonymous'] || $post['in_group'] || $post['in_event'] || in_array($post['post_type'], ['article', 'product', 'funding'])) { _error(400); } /* check if viewer can edit privacy */ if ($post['manage_post'] && $post['user_type'] == 'user' && !$post['in_group'] && !$post['in_event'] && $post['post_type'] != "product") { /* update privacy */ $db->query(sprintf("UPDATE posts SET privacy = %s WHERE post_id = %s", secure($privacy), secure($post_id, 'int'))); } else { _error(403); } } /** * disallow_post * * @param integer $post_id * @return void */ public function disallow_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* check if post is_anonymous */ if ($post['is_anonymous']) { throw new Exception(__("You can not do this with anonymous post")); } /* set post as hidden */ $db->query(sprintf("UPDATE posts SET is_hidden = '1' WHERE post_id = %s", secure($post_id, 'int'))); } /** * allow_post * * @param integer $post_id * @return void */ public function allow_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* check if post is_anonymous */ if ($post['is_anonymous']) { throw new Exception(__("You can not do this with anonymous post")); } /* set post as not hidden */ $db->query(sprintf("UPDATE posts SET is_hidden = '0' WHERE post_id = %s", secure($post_id, 'int'))); } /** * disable_post_comments * * @param integer $post_id * @return void */ public function disable_post_comments($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* trun off post commenting */ $db->query(sprintf("UPDATE posts SET comments_disabled = '1' WHERE post_id = %s", secure($post_id, 'int'))); } /** * enable_post_comments * * @param integer $post_id * @return void */ public function enable_post_comments($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* trun on post commenting */ $db->query(sprintf("UPDATE posts SET comments_disabled = '0' WHERE post_id = %s", secure($post_id, 'int'))); } /** * approve_post * * @param integer $post_id * @return void */ public function approve_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can approve post */ if ($post['in_group']) { if (!$post['is_group_admin']) { _error(403); } /* approve post */ $db->query(sprintf("UPDATE posts SET group_approved = '1' WHERE post_id = %s", secure($post_id, 'int'))); /* send notification to the post author */ $this->post_notification(['to_user_id' => $post['author_id'], 'action' => 'group_post_approval', 'node_type' => $post['group_title'], 'node_url' => $post['group_name']]); } elseif ($post['in_event']) { if (!$post['is_event_admin']) { _error(403); } /* approve post */ $db->query(sprintf("UPDATE posts SET event_approved = '1' WHERE post_id = %s", secure($post_id, 'int'))); /* send notification to the post author */ $this->post_notification(['to_user_id' => $post['author_id'], 'action' => 'event_post_approval', 'node_type' => $post['event_title'], 'node_url' => $post['event_id']]); } } /** * sold_post * * @param integer $post_id * @return void */ public function sold_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* sold post */ $db->query(sprintf("UPDATE posts_products SET available = '0' WHERE post_id = %s", secure($post_id, 'int'))); } /** * unsold_post * * @param integer $post_id * @return void */ public function unsold_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* unsold post */ $db->query(sprintf("UPDATE posts_products SET available = '1' WHERE post_id = %s", secure($post_id, 'int'))); } /** * closed_post * * @param integer $post_id * @return void */ public function closed_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* close post */ switch ($post['post_type']) { case 'job': $table = "posts_jobs"; break; case 'course': $table = "posts_courses"; break; } $db->query(sprintf("UPDATE $table SET available = '0' WHERE post_id = %s", secure($post_id, 'int'))); } /** * unclosed_post * * @param integer $post_id * @return void */ public function unclosed_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* unclose post */ switch ($post['post_type']) { case 'job': $table = "posts_jobs"; break; case 'course': $table = "posts_courses"; break; } $db->query(sprintf("UPDATE $table SET available = '1' WHERE post_id = %s", secure($post_id, 'int'))); } /** * save_post * * @param integer $post_id * @return void */ public function save_post($post_id) { global $db, $date; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* save post */ if (!$post['i_save']) { $db->query(sprintf("INSERT INTO posts_saved (post_id, user_id, time) VALUES (%s, %s, %s)", secure($post_id, 'int'), secure($this->_data['user_id'], 'int'), secure($date))); } } /** * unsave_post * * @param integer $post_id * @return void */ public function unsave_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* unsave post */ if ($post['i_save']) { $db->query(sprintf("DELETE FROM posts_saved WHERE post_id = %s AND user_id = %s", secure($post_id, 'int'), secure($this->_data['user_id'], 'int'))); } } /** * boost_post * * @param integer $post_id * @return void */ public function boost_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* check if viewer can boost post */ if (!$this->_data['can_boost_posts']) { modal("MESSAGE", __("Sorry"), __("You reached the maximum number of boosted posts! Upgrade your package to get more")); } /* check if the post in_group or in_event */ if ($post['in_group'] || $post['in_event']) { throw new Exception(__("You can't boost a post from a group or event")); } /* boost post */ if (!$post['boosted']) { /* boost post */ $db->query(sprintf("UPDATE posts SET boosted = '1', boosted_by = %s WHERE post_id = %s", secure($this->_data['user_id'], 'int'), secure($post_id, 'int'))); /* update user */ $db->query(sprintf("UPDATE users SET user_boosted_posts = user_boosted_posts + 1 WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); } } /** * unboost_post * * @param integer $post_id * @return void */ public function unboost_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* unboost post */ if ($post['boosted']) { /* unboost post */ $db->query(sprintf("UPDATE posts SET boosted = '0', boosted_by = NULL WHERE post_id = %s", secure($post_id, 'int'))); /* update user */ $db->query(sprintf("UPDATE users SET user_boosted_posts = IF(user_boosted_posts=0,0,user_boosted_posts-1) WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); } } /** * pin_post * * @param integer $post_id * @return void */ public function pin_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* check if post is_anonymous */ if ($post['is_anonymous']) { throw new Exception(__("You can not do this with anonymous post")); } /* pin post */ if (!$post['pinned']) { /* check the post author type */ if ($post['user_type'] == "user") { /* user */ if ($post['in_group']) { if (!$post['is_group_admin']) { throw new Exception(__("Only group admin can pin the post")); } /* update group */ $db->query(sprintf("UPDATE `groups` SET group_pinned_post = %s WHERE group_id = %s", secure($post_id, 'int'), secure($post['group_id'], 'int'))); } elseif ($post['in_event']) { if (!$post['is_event_admin']) { throw new Exception(__("Only event admin can pin the post")); } /* update event */ $db->query(sprintf("UPDATE `events` SET event_pinned_post = %s WHERE event_id = %s", secure($post_id, 'int'), secure($post['event_id'], 'int'))); } else { /* update user */ $db->query(sprintf("UPDATE users SET user_pinned_post = %s WHERE user_id = %s", secure($post_id, 'int'), secure($post['author_id'], 'int'))); } } else { /* update page */ $db->query(sprintf("UPDATE pages SET page_pinned_post = %s WHERE page_id = %s", secure($post_id, 'int'), secure($post['user_id'], 'int'))); } } } /** * unpin_post * * @param integer $post_id * @return void */ public function unpin_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* check if post is_anonymous */ if ($post['is_anonymous']) { throw new Exception(__("You can not do this with anonymous post")); } /* pin post */ if ($post['pinned']) { /* check the post author type */ if ($post['user_type'] == "user") { /* user */ if ($post['in_group']) { if (!$post['is_group_admin']) { throw new Exception(__("Only group admin can unpin the post")); } /* update group */ $db->query(sprintf("UPDATE `groups` SET group_pinned_post = '0' WHERE group_id = %s", secure($post['group_id'], 'int'))); } elseif ($post['in_event']) { if (!$post['is_event_admin']) { throw new Exception(__("Only event admin can unpin the post")); } /* update event */ $db->query(sprintf("UPDATE `events` SET event_pinned_post = '0' WHERE event_id = %s", secure($post['event_id'], 'int'))); } else { /* update user */ $db->query(sprintf("UPDATE users SET user_pinned_post = '0' WHERE user_id = %s", secure($post['user_id'], 'int'))); } } else { /* update page */ $db->query(sprintf("UPDATE pages SET page_pinned_post = '0' WHERE page_id = %s", secure($post['user_id'], 'int'))); } } } /** * monetize_post * * @param integer $post_id * @return void */ public function monetize_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post']) { _error(403); } /* check if post can be monetized */ if (!$post['can_be_for_subscriptions']) { _error(403); } /* monetize post */ if (!$post['for_subscriptions']) { /* update post */ $db->query(sprintf("UPDATE posts SET for_subscriptions = '1' WHERE post_id = %s", secure($post_id, 'int'))); } } /** * unmonetize_post * * @param integer $post_id * @return void */ public function unmonetize_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id, true); if (!$post) { _error(403); } /* check if viewer can edit post */ if (!$post['manage_post'] && !$post['is_group_admin'] && !$post['is_event_admin']) { _error(403); } /* check if post can be monetized */ if (!$post['can_be_for_subscriptions']) { _error(403); } /* unmonetize post */ if ($post['for_subscriptions']) { /* update post */ $db->query(sprintf("UPDATE posts SET for_subscriptions = '0' WHERE post_id = %s", secure($post_id, 'int'))); } } /** * react_post * * @param integer $post_id * @param string $reaction * @return void */ public function react_post($post_id, $reaction) { global $db, $date; /* check reation */ if (!in_array($reaction, ['like', 'love', 'haha', 'yay', 'wow', 'sad', 'angry'])) { _error(403); } /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check blocking */ if ($post['user_type'] == "user" && $this->blocked($post['author_id'])) { _error(403); } /* react the post */ if ($post['i_react']) { /* remove any previous reaction */ $db->query(sprintf("DELETE FROM posts_reactions WHERE user_id = %s AND post_id = %s", secure($this->_data['user_id'], 'int'), secure($post_id, 'int'))); /* update post reaction counter */ $reaction_field = "reaction_" . $post['i_reaction'] . "_count"; $db->query(sprintf("UPDATE posts SET $reaction_field = IF($reaction_field=0,0,$reaction_field-1) WHERE post_id = %s", secure($post_id, 'int'))); /* delete notification */ $this->delete_notification($post['author_id'], 'react_' . $post['i_reaction'], 'post', $post_id); /* points balance */ $this->points_balance("delete", $post['author_id'], "post_reaction"); $this->points_balance("delete", $this->_data['user_id'], "posts_reactions"); } $db->query(sprintf("INSERT INTO posts_reactions (user_id, post_id, reaction, reaction_time) VALUES (%s, %s, %s, %s)", secure($this->_data['user_id'], 'int'), secure($post_id, 'int'), secure($reaction), secure($date))); $reaction_id = $db->insert_id; /* update post reaction counter */ $reaction_field = "reaction_" . $reaction . "_count"; $db->query(sprintf("UPDATE posts SET $reaction_field = $reaction_field + 1 WHERE post_id = %s", secure($post_id, 'int'))); /* post notification */ $this->post_notification(['to_user_id' => $post['author_id'], 'action' => 'react_' . $reaction, 'node_type' => 'post', 'node_url' => $post_id]); /* points balance */ $this->points_balance("add", $post['author_id'], "post_reaction", $reaction_id); $this->points_balance("add", $this->_data['user_id'], "posts_reactions", $reaction_id); } /** * unreact_post * * @param integer $post_id * @param string $reaction * @return void */ public function unreact_post($post_id, $reaction) { global $db; /* check reation */ if (!in_array($reaction, ['like', 'love', 'haha', 'yay', 'wow', 'sad', 'angry'])) { _error(403); } /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check blocking */ if ($post['user_type'] == "user" && $this->blocked($post['author_id'])) { _error(403); } /* unreact the post */ if ($post['i_react']) { $db->query(sprintf("DELETE FROM posts_reactions WHERE user_id = %s AND post_id = %s", secure($this->_data['user_id'], 'int'), secure($post_id, 'int'))); /* update post reaction counter */ $reaction_field = "reaction_" . $reaction . "_count"; $db->query(sprintf("UPDATE posts SET $reaction_field = IF($reaction_field=0,0,$reaction_field-1) WHERE post_id = %s", secure($post_id, 'int'))); /* delete notification */ $this->delete_notification($post['author_id'], 'react_' . $reaction, 'post', $post_id); /* points balance */ $this->points_balance("delete", $post['author_id'], "post_reaction", $reaction_id); $this->points_balance("delete", $this->_data['user_id'], "posts_reactions"); } } /** * hide_post * * @param integer $post_id * @return void */ public function hide_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* check blocking */ if ($post['user_type'] == "user" && $this->blocked($post['author_id'])) { _error(403); } /* hide the post */ $db->query(sprintf("INSERT INTO posts_hidden (user_id, post_id) VALUES (%s, %s)", secure($this->_data['user_id'], 'int'), secure($post_id, 'int'))); } /** * unhide_post * * @param integer $post_id * @return void */ public function unhide_post($post_id) { global $db; /* (check|get) post */ $post = $this->_check_post($post_id); if (!$post) { _error(403); } /* unhide the post */ $db->query(sprintf("DELETE FROM posts_hidden WHERE user_id = %s AND post_id = %s", secure($this->_data['user_id'], 'int'), secure($post_id, 'int'))); } /** * add_vote * * @param integer $option_id * @return void */ public function add_vote($option_id) { global $db; /* get poll */ $get_poll = $db->query(sprintf("SELECT posts_polls.* FROM posts_polls_options INNER JOIN posts_polls ON posts_polls_options.poll_id = posts_polls.poll_id WHERE option_id = %s", secure($option_id, 'int'))); if ($get_poll->num_rows == 0) { _error(403); } $poll = $get_poll->fetch_assoc(); /* (check|get) post */ $post = $this->_check_post($poll['post_id']); if (!$post) { _error(403); } /* check blocking */ if ($post['user_type'] == "user" && $this->blocked($post['author_id'])) { _error(403); } /* insert user vote */ $vote = $db->query(sprintf("INSERT INTO posts_polls_options_users (user_id, poll_id, option_id) VALUES (%s, %s, %s)", secure($this->_data['user_id'], 'int'), secure($poll['poll_id'], 'int'), secure($option_id, 'int'))); if ($vote) { /* update poll votes */ $db->query(sprintf("UPDATE posts_polls SET votes = votes + 1 WHERE poll_id = %s", secure($poll['poll_id'], 'int'))); /* post notification */ $this->post_notification(['to_user_id' => $post['author_id'], 'action' => 'vote', 'node_type' => 'post', 'node_url' => $post['post_id']]); } } /** * delete_vote * * @param integer $option_id * @return void */ public function delete_vote($option_id) { global $db; /* get poll */ $get_poll = $db->query(sprintf("SELECT posts_polls.* FROM posts_polls_options INNER JOIN posts_polls ON posts_polls_options.poll_id = posts_polls.poll_id WHERE option_id = %s", secure($option_id, 'int'))); if ($get_poll->num_rows == 0) { _error(403); } $poll = $get_poll->fetch_assoc(); /* (check|get) post */ $post = $this->_check_post($poll['post_id']); if (!$post) { _error(403); } /* check blocking */ if ($post['user_type'] == "user" && $this->blocked($post['author_id'])) { _error(403); } /* delete user vote */ $db->query(sprintf("DELETE FROM posts_polls_options_users WHERE user_id = %s AND poll_id = %s AND option_id = %s", secure($this->_data['user_id'], 'int'), secure($poll['poll_id'], 'int'), secure($option_id, 'int'))); if ($db->affected_rows > 0) { /* update poll votes */ $db->query(sprintf("UPDATE posts_polls SET votes = IF(votes=0,0,votes-1) WHERE poll_id = %s", secure($poll['poll_id'], 'int'))); /* delete notification */ $this->delete_notification($post['author_id'], 'vote', 'post', $post['post_id']); } } /** * change_vote * * @param integer $option_id * @param integer $checked_id * @return void */ public function change_vote($option_id, $checked_id) { global $db; /* get poll */ $get_poll = $db->query(sprintf("SELECT posts_polls.* FROM posts_polls_options INNER JOIN posts_polls ON posts_polls_options.poll_id = posts_polls.poll_id WHERE option_id = %s", secure($option_id, 'int'))); if ($get_poll->num_rows == 0) { _error(403); } $poll = $get_poll->fetch_assoc(); /* (check|get) post */ $post = $this->_check_post($poll['post_id']); if (!$post) { _error(403); } /* check blocking */ if ($post['user_type'] == "user" && $this->blocked($post['author_id'])) { _error(403); } /* delete old vote */ $db->query(sprintf("DELETE FROM posts_polls_options_users WHERE user_id = %s AND poll_id = %s AND option_id = %s", secure($this->_data['user_id'], 'int'), secure($poll['poll_id'], 'int'), secure($checked_id, 'int'))); if ($db->affected_rows > 0) { /* insert new vote */ $db->query(sprintf("INSERT INTO posts_polls_options_users (user_id, poll_id, option_id) VALUES (%s, %s, %s)", secure($this->_data['user_id'], 'int'), secure($poll['poll_id'], 'int'), secure($option_id, 'int'))); } } /** * update_media_views * * @param string $media_type * @param integer $video_id * @return void */ public function update_media_views($media_type, $media_id) { global $db; switch ($media_type) { case 'reel': $db->query(sprintf("UPDATE posts_reels SET views = views + 1 WHERE reel_id = %s", secure($media_id, 'int'))); break; case 'video': $db->query(sprintf("UPDATE posts_videos SET views = views + 1 WHERE video_id = %s", secure($media_id, 'int'))); break; case 'audio': $db->query(sprintf("UPDATE posts_audios SET views = views + 1 WHERE audio_id = %s", secure($media_id, 'int'))); break; } } /* ------------------------------- */ /* Comments */ /* ------------------------------- */ /** * get_comments * * @param integer $node_id * @param integer $offset * @param boolean $is_post * @param boolean $pass_privacy_check * @param array $post * @param string $sorting * @return array */ public function get_comments($node_id, $offset = 0, $is_post = true, $pass_privacy_check = true, $post = [], $sorting = "recent", $last_comment_id = null) { global $db, $system; $comments = []; $offset *= $system['min_results']; switch ($sorting) { case 'top': $order_query = " ORDER BY posts_comments.reaction_like_count DESC, posts_comments.reaction_love_count DESC, posts_comments.reaction_haha_count DESC, posts_comments.reaction_yay_count DESC, posts_comments.reaction_wow_count DESC, posts_comments.reaction_sad_count DESC, posts_comments.reaction_angry_count DESC, posts_comments.replies DESC"; break; case 'all': $order_query = " ORDER BY posts_comments.comment_id ASC "; break; default: $order_query = " ORDER BY posts_comments.comment_id DESC "; break; } /* get comments */ if ($is_post) { /* get post comments */ if (!$pass_privacy_check) { /* (check|get) post */ $post = $this->_check_post($node_id, false); if (!$post) { return false; } } /* get post comments */ if (!$last_comment_id) { $get_comments = $db->query(sprintf("SELECT posts_comments.*, users.user_name, users.user_firstname, users.user_lastname, users.user_gender, users.user_picture, users.user_verified, users.user_subscribed, packages.name as package_name, pages.* FROM posts_comments LEFT JOIN users ON posts_comments.user_id = users.user_id AND posts_comments.user_type = 'user' LEFT JOIN packages ON users.user_subscribed = '1' AND users.user_package = packages.package_id LEFT JOIN pages ON posts_comments.user_id = pages.page_id AND posts_comments.user_type = 'page' WHERE NOT (users.user_name <=> NULL AND pages.page_name <=> NULL) AND posts_comments.node_type = 'post' AND posts_comments.node_id = %s " . $order_query . " LIMIT %s, %s", secure($node_id, 'int'), secure($offset, 'int', false), secure($system['min_results'], 'int', false))); } else { $get_comments = $db->query(sprintf("SELECT posts_comments.*, users.user_name, users.user_firstname, users.user_lastname, users.user_gender, users.user_picture, users.user_verified, users.user_subscribed, packages.name as package_name, pages.* FROM posts_comments LEFT JOIN users ON posts_comments.user_id = users.user_id AND posts_comments.user_type = 'user' LEFT JOIN packages ON users.user_subscribed = '1' AND users.user_package = packages.package_id LEFT JOIN pages ON posts_comments.user_id = pages.page_id AND posts_comments.user_type = 'page' WHERE NOT (users.user_name <=> NULL AND pages.page_name <=> NULL) AND posts_comments.node_type = 'post' AND posts_comments.node_id = %s AND posts_comments.comment_id > %s " . $order_query, secure($node_id, 'int'), secure($last_comment_id, 'int'))); } } else { /* get photo comments */ /* check privacy */ if (!$pass_privacy_check) { /* (check|get) photo */ $photo = $this->get_photo($node_id); if (!$photo) { _error(403); } $post = $photo['post']; } /* get photo comments */ $get_comments = $db->query(sprintf("SELECT posts_comments.*, users.user_name, users.user_firstname, users.user_lastname, users.user_gender, users.user_picture, users.user_verified, users.user_subscribed, packages.name as package_name, pages.* FROM posts_comments LEFT JOIN users ON posts_comments.user_id = users.user_id AND posts_comments.user_type = 'user' LEFT JOIN packages ON users.user_subscribed = '1' AND users.user_package = packages.package_id LEFT JOIN pages ON posts_comments.user_id = pages.page_id AND posts_comments.user_type = 'page' WHERE NOT (users.user_name <=> NULL AND pages.page_name <=> NULL) AND posts_comments.node_type = 'photo' AND posts_comments.node_id = %s " . $order_query . " LIMIT %s, %s", secure($node_id, 'int'), secure($offset, 'int', false), secure($system['min_results'], 'int', false))); } if ($get_comments->num_rows == 0) { return $comments; } while ($comment = $get_comments->fetch_assoc()) { /* pass comments_disabled from post to comment */ $comment['comments_disabled'] = $post['comments_disabled']; /* check if the page has been deleted */ if ($comment['user_type'] == "page" && !$comment['page_admin']) { continue; } /* check if there is any blocking between the viewer & the comment author */ if ($comment['user_type'] == "user" && $this->blocked($comment['user_id'])) { continue; } /* get reactions array */ $comment['reactions']['like'] = $comment['reaction_like_count']; $comment['reactions']['love'] = $comment['reaction_love_count']; $comment['reactions']['haha'] = $comment['reaction_haha_count']; $comment['reactions']['yay'] = $comment['reaction_yay_count']; $comment['reactions']['wow'] = $comment['reaction_wow_count']; $comment['reactions']['sad'] = $comment['reaction_sad_count']; $comment['reactions']['angry'] = $comment['reaction_angry_count']; arsort($comment['reactions']); /* get total reactions */ $comment['reactions_total_count'] = $comment['reaction_like_count'] + $comment['reaction_love_count'] + $comment['reaction_haha_count'] + $comment['reaction_yay_count'] + $comment['reaction_wow_count'] + $comment['reaction_sad_count'] + $comment['reaction_angry_count']; $comment['reactions_total_count_formatted'] = abbreviate_count($comment['reactions_total_count']); /* get replies */ if ($comment['replies'] > 0) { $comment['comment_replies'] = $this->get_replies($comment['comment_id'], 0, true, $post); } /* parse text */ $comment['text_plain'] = $comment['text']; $comment['text'] = $this->_parse(["text" => $comment['text']]); /* get the comment author */ if ($comment['user_type'] == "user") { /* user type */ $comment['author_id'] = $comment['user_id']; $comment['author_picture'] = get_picture($comment['user_picture'], $comment['user_gender']); $comment['author_url'] = $system['system_url'] . '/' . $comment['user_name']; $comment['author_name'] = ($system['show_usernames_enabled']) ? $comment['user_name'] : $comment['user_firstname'] . " " . $comment['user_lastname']; $comment['author_verified'] = $comment['user_verified']; } else { /* page type */ $comment['author_id'] = $comment['page_admin']; $comment['author_picture'] = get_picture($comment['page_picture'], "page"); $comment['author_url'] = $system['system_url'] . '/pages/' . $comment['page_name']; $comment['author_name'] = $comment['page_title']; $comment['author_verified'] = $comment['page_verified']; } /* check if viewer user react this comment */ $comment['i_react'] = false; if ($this->_logged_in) { /* reaction */ if ($comment['reactions_total_count'] > 0) { $get_reaction = $db->query(sprintf("SELECT reaction FROM posts_comments_reactions WHERE user_id = %s AND comment_id = %s", secure($this->_data['user_id'], 'int'), secure($comment['comment_id'], 'int'))); if ($get_reaction->num_rows > 0) { $comment['i_react'] = true; $comment['i_reaction'] = $get_reaction->fetch_assoc()['reaction']; } } } /* check if viewer can manage comment [Edit|Delete] */ $comment['edit_comment'] = false; $comment['delete_comment'] = false; if ($this->_logged_in) { /* viewer is (admin|moderator) */ if ($this->_data['user_group'] < 3) { $comment['edit_comment'] = true; $comment['delete_comment'] = true; } /* viewer is the author of comment */ if ($this->_data['user_id'] == $comment['author_id']) { $comment['edit_comment'] = true; $comment['delete_comment'] = true; } /* viewer is the author of post */ if ($this->_data['user_id'] == $post['author_id']) { $comment['delete_comment'] = true; } /* viewer is the admin of the group of the post */ if ($post['in_group'] && $post['is_group_admin']) { $comment['delete_comment'] = true; } /* viewer is the admin of the event of the post */ if ($post['in_event'] && $post['is_event_admin']) { $comment['delete_comment'] = true; } } $comments[] = $comment; } return $comments; } /** * get_replies * * @param integer $comment_id * @param integer $offset * @param boolean $offset * @param array $post * @return array */ public function get_replies($comment_id, $offset = 0, $pass_check = true, $post = []) { global $db, $system; $replies = []; $offset *= $system['min_results']; if (!$pass_check) { $comment = $this->get_comment($comment_id); if (!$comment) { _error(403); } $post_author_id = $comment['post']['author_id']; } else { $post_author_id = $post['author_id']; } /* get replies */ $get_replies = $db->query(sprintf("SELECT * FROM (SELECT posts_comments.*, users.user_name, users.user_firstname, users.user_lastname, users.user_gender, users.user_picture, users.user_verified, users.user_subscribed, packages.name as package_name, pages.* FROM posts_comments LEFT JOIN users ON posts_comments.user_id = users.user_id AND posts_comments.user_type = 'user' LEFT JOIN packages ON users.user_subscribed = '1' AND users.user_package = packages.package_id LEFT JOIN pages ON posts_comments.user_id = pages.page_id AND posts_comments.user_type = 'page' WHERE NOT (users.user_name <=> NULL AND pages.page_name <=> NULL) AND posts_comments.node_type = 'comment' AND posts_comments.node_id = %s ORDER BY posts_comments.comment_id DESC LIMIT %s, %s) comments ORDER BY comments.comment_id ASC", secure($comment_id, 'int'), secure($offset, 'int', false), secure($system['min_results'], 'int', false))); if ($get_replies->num_rows == 0) { return $replies; } while ($reply = $get_replies->fetch_assoc()) { /* pass comments_disabled from (post|comment) to reply */ $reply['comments_disabled'] = (isset($post['comments_disabled'])) ? $post['comments_disabled'] : $comment['comments_disabled']; /* check if the page has been deleted */ if ($reply['user_type'] == "page" && !$reply['page_admin']) { continue; } /* check if there is any blocking between the viewer & the comment author */ if ($reply['user_type'] == "user" && $this->blocked($reply['user_id'])) { continue; } /* get reactions array */ $reply['reactions']['like'] = $reply['reaction_like_count']; $reply['reactions']['love'] = $reply['reaction_love_count']; $reply['reactions']['haha'] = $reply['reaction_haha_count']; $reply['reactions']['yay'] = $reply['reaction_yay_count']; $reply['reactions']['wow'] = $reply['reaction_wow_count']; $reply['reactions']['sad'] = $reply['reaction_sad_count']; $reply['reactions']['angry'] = $reply['reaction_angry_count']; arsort($reply['reactions']); /* get total reactions */ $reply['reactions_total_count'] = $reply['reaction_like_count'] + $reply['reaction_love_count'] + $reply['reaction_haha_count'] + $reply['reaction_yay_count'] + $reply['reaction_wow_count'] + $reply['reaction_sad_count'] + $reply['reaction_angry_count']; $reply['reactions_total_count_formatted'] = abbreviate_count($reply['reactions_total_count']); /* parse text */ $reply['text_plain'] = $reply['text']; $reply['text'] = $this->_parse(["text" => $reply['text']]); /* get the reply author */ if ($reply['user_type'] == "user") { /* user type */ $reply['author_id'] = $reply['user_id']; $reply['author_picture'] = get_picture($reply['user_picture'], $reply['user_gender']); $reply['author_url'] = $system['system_url'] . '/' . $reply['user_name']; $reply['author_user_name'] = $reply['user_name']; $reply['author_name'] = ($system['show_usernames_enabled']) ? $reply['user_name'] : $reply['user_firstname'] . " " . $reply['user_lastname']; $reply['author_verified'] = $reply['user_verified']; } else { /* page type */ $reply['author_id'] = $reply['page_admin']; $reply['author_picture'] = get_picture($reply['page_picture'], "page"); $reply['author_url'] = $system['system_url'] . '/pages/' . $reply['page_name']; $reply['author_name'] = $reply['page_title']; $reply['author_verified'] = $reply['page_verified']; } /* check if viewer user react this reply */ $reply['i_react'] = false; if ($this->_logged_in) { /* reaction */ if ($reply['reactions_total_count'] > 0) { $get_reaction = $db->query(sprintf("SELECT reaction FROM posts_comments_reactions WHERE user_id = %s AND comment_id = %s", secure($this->_data['user_id'], 'int'), secure($reply['comment_id'], 'int'))); if ($get_reaction->num_rows > 0) { $reply['i_react'] = true; $reply['i_reaction'] = $get_reaction->fetch_assoc()['reaction']; } } } /* check if viewer can manage reply [Edit|Delete] */ $reply['edit_comment'] = false; $reply['delete_comment'] = false; if ($this->_logged_in) { /* viewer is (admin|moderator) */ if ($this->_data['user_group'] < 3) { $reply['edit_comment'] = true; $reply['delete_comment'] = true; } /* viewer is the author of reply */ if ($this->_data['user_id'] == $reply['author_id']) { $reply['edit_comment'] = true; $reply['delete_comment'] = true; } /* viewer is the author of post */ if ($this->_data['user_id'] == $post_author_id) { $reply['delete_comment'] = true; } } $replies[] = $reply; } return $replies; } /** * comment * * @param string $handle * @param integer $node_id * @param string $message * @param string $photo * @param string $voice_note * @return array */ public function comment($handle, $node_id, $message, $photo, $voice_note) { global $db, $system, $date; /* check max comments/hour limit */ if ($system['max_comments_hour'] > 0 && $this->_data['user_group'] >= 3) { $check_limit = $db->query(sprintf("SELECT COUNT(*) as count FROM posts_comments WHERE posts_comments.time >= DATE_SUB(NOW(),INTERVAL 1 HOUR) AND user_id = %s AND user_type = 'user'", secure($this->_data['user_id'], 'int'))); if ($check_limit->fetch_assoc()['count'] >= $system['max_comments_hour']) { modal("MESSAGE", __("Maximum Limit Reached"), __("You have reached the maximum limit of comments/hour, please try again later")); } } /* check comment max length */ if ($system['max_comment_length'] > 0 && $this->_data['user_group'] >= 3) { if (strlen($message) >= $system['max_comment_length']) { modal("MESSAGE", __("Text Length Limit Reached"), __("Your message characters length is over the allowed limit") . " (" . $system['max_comment_length'] . " " . __("Characters") . ")"); } } /* default */ $comment = []; $comment['node_id'] = $node_id; $comment['node_type'] = $handle; $comment['text'] = $message; $comment['image'] = $photo; $comment['voice_note'] = $voice_note; $comment['time'] = $date; $comment['reaction_like_count'] = 0; $comment['reaction_love_count'] = 0; $comment['reaction_haha_count'] = 0; $comment['reaction_yay_count'] = 0; $comment['reaction_wow_count'] = 0; $comment['reaction_sad_count'] = 0; $comment['reaction_angry_count'] = 0; $comment['reactions_total_count'] = 0; $comment['replies'] = 0; /* check the handle */ switch ($handle) { case 'post': /* (check|get) post */ $post = $this->_check_post($node_id, false, false); if (!$post) { _error(403); } break; case 'photo': /* (check|get) photo */ $photo = $this->get_photo($node_id); if (!$photo) { _error(403); } $post = $photo['post']; break; case 'comment': /* (check|get) comment */ $parent_comment = $this->get_comment($node_id, false); if (!$parent_comment) { _error(403); } $post = $parent_comment['post']; break; } /* check if comments disabled */ if ($post['comments_disabled']) { throw new Exception(__("Comments disabled for this post")); } /* check if there is any blocking between the viewer & the target */ if (($post['user_type'] == "user" && $this->blocked($post['author_id'])) || ($handle == "comment" && $this->blocked($parent_comment['author_id']))) { _error(403); } /* check if the viewer is page admin of the target post */ if (!$post['is_page_admin']) { $comment['user_id'] = $this->_data['user_id']; $comment['user_type'] = "user"; $comment['author_picture'] = $this->_data['user_picture']; $comment['author_url'] = $system['system_url'] . '/' . $this->_data['user_name']; $comment['author_user_name'] = $this->_data['user_name']; $comment['author_name'] = $this->_data['name']; $comment['author_verified'] = $this->_data['user_verified']; } else { $comment['user_id'] = $post['page_id']; $comment['user_type'] = "page"; $comment['author_picture'] = get_picture($post['page_picture'], "page"); $comment['author_url'] = $system['system_url'] . '/pages/' . $post['page_name']; $comment['author_name'] = $post['page_title']; $comment['author_verified'] = $post['page_verified']; } /* insert the comment */ $db->query(sprintf("INSERT INTO posts_comments (node_id, node_type, user_id, user_type, text, image, voice_note, time) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)", secure($comment['node_id'], 'int'), secure($comment['node_type']), secure($comment['user_id'], 'int'), secure($comment['user_type']), secure($comment['text']), secure($comment['image']), secure($comment['voice_note']), secure($comment['time']))); $comment['comment_id'] = $db->insert_id; /* update (post|photo|comment) (comments|replies) counter */ switch ($handle) { case 'post': $db->query(sprintf("UPDATE posts SET comments = comments + 1 WHERE post_id = %s", secure($node_id, 'int'))); break; case 'photo': $db->query(sprintf("UPDATE posts_photos SET comments = comments + 1 WHERE photo_id = %s", secure($node_id, 'int'))); break; case 'comment': $db->query(sprintf("UPDATE posts_comments SET replies = replies + 1 WHERE comment_id = %s", secure($node_id, 'int'))); if ($parent_comment['node_type'] == "post") { $db->query(sprintf("UPDATE posts SET comments = comments + 1 WHERE post_id = %s", secure($parent_comment['node_id'], 'int'))); } elseif ($parent_comment['node_type'] == "photo") { $db->query(sprintf("UPDATE posts_photos SET comments = comments + 1 WHERE photo_id = %s", secure($parent_comment['node_id'], 'int'))); } break; } /* post notification */ if ($handle == "comment") { $this->post_notification(['to_user_id' => $parent_comment['author_id'], 'from_user_id' => $comment['user_id'], 'from_user_type' => $comment['user_type'], 'action' => 'reply', 'node_type' => $parent_comment['node_type'], 'node_url' => $parent_comment['node_id'], 'notify_id' => 'comment_' . $comment['comment_id']]); if ($post['author_id'] != $parent_comment['author_id']) { $this->post_notification(['to_user_id' => $post['author_id'], 'action' => 'comment', 'node_type' => $parent_comment['node_type'], 'node_url' => $parent_comment['node_id'], 'notify_id' => 'comment_' . $comment['comment_id']]); } } else { $this->post_notification(['to_user_id' => $post['author_id'], 'action' => 'comment', 'node_type' => $handle, 'node_url' => $node_id, 'notify_id' => 'comment_' . $comment['comment_id']]); } /* post mention notifications if any */ if ($handle == "comment") { $this->post_mentions($comment['text'], $parent_comment['node_id'], "reply_" . $parent_comment['node_type'], 'comment_' . $comment['comment_id'], [$post['author_id'], $parent_comment['author_id']]); } else { $this->post_mentions($comment['text'], $node_id, "comment_" . $handle, 'comment_' . $comment['comment_id'], [$post['author_id']]); } /* parse text */ $comment['text_plain'] = htmlentities($comment['text'], ENT_QUOTES, 'utf-8'); $comment['text'] = $this->_parse(["text" => $comment['text_plain']]); /* check if viewer can manage comment [Edit|Delete] */ $comment['edit_comment'] = true; $comment['delete_comment'] = true; /* points balance */ $this->points_balance("add", $post['author_id'], "post_comment", $comment['comment_id']); $this->points_balance("add", $this->_data['user_id'], "comment", $comment['comment_id']); /* return */ return $comment; } /** * get_comment * * @param integer $comment_id * @return array|false */ public function get_comment($comment_id, $recursive = true) { global $db; /* get comment */ $get_comment = $db->query(sprintf("SELECT posts_comments.*, pages.page_admin FROM posts_comments LEFT JOIN pages ON posts_comments.user_type = 'page' AND posts_comments.user_id = pages.page_id WHERE posts_comments.comment_id = %s", secure($comment_id, 'int'))); if ($get_comment->num_rows == 0) { return false; } $comment = $get_comment->fetch_assoc(); /* check if the page has been deleted */ if ($comment['user_type'] == "page" && !$comment['page_admin']) { return false; } /* check if there is any blocking between the viewer & the comment author */ if ($comment['user_type'] == "user" && $this->blocked($comment['user_id'])) { return false; } /* get reactions array */ $comment['reactions']['like'] = $comment['reaction_like_count']; $comment['reactions']['love'] = $comment['reaction_love_count']; $comment['reactions']['haha'] = $comment['reaction_haha_count']; $comment['reactions']['yay'] = $comment['reaction_yay_count']; $comment['reactions']['wow'] = $comment['reaction_wow_count']; $comment['reactions']['sad'] = $comment['reaction_sad_count']; $comment['reactions']['angry'] = $comment['reaction_angry_count']; arsort($comment['reactions']); /* get total reactions */ $comment['reactions_total_count'] = $comment['reaction_like_count'] + $comment['reaction_love_count'] + $comment['reaction_haha_count'] + $comment['reaction_yay_count'] + $comment['reaction_wow_count'] + $comment['reaction_sad_count'] + $comment['reaction_angry_count']; $comment['reactions_total_count_formatted'] = abbreviate_count($comment['reactions_total_count']); /* get the author */ $comment['author_id'] = ($comment['user_type'] == "page") ? $comment['page_admin'] : $comment['user_id']; /* get post */ switch ($comment['node_type']) { case 'post': $post = $this->_check_post($comment['node_id'], false, false); /* check if the post has been deleted */ if (!$post) { return false; } $comment['post'] = $post; break; case 'photo': /* (check|get) photo */ $photo = $this->get_photo($comment['node_id']); if (!$photo) { return false; } $comment['post'] = $photo['post']; break; case 'comment': if (!$recursive) { return false; } /* (check|get) comment */ $parent_comment = $this->get_comment($comment['node_id'], false); if (!$parent_comment) { return false; } $comment['parent_comment'] = $parent_comment; $comment['post'] = $parent_comment['post']; break; } /* pass comments_disabled from post to comment */ $comment['comments_disabled'] = $comment['post']['comments_disabled']; /* check if viewer user react this comment */ $comment['i_react'] = false; if ($this->_logged_in) { /* reaction */ if ($comment['reactions_total_count'] > 0) { $get_reaction = $db->query(sprintf("SELECT reaction FROM posts_comments_reactions WHERE user_id = %s AND comment_id = %s", secure($this->_data['user_id'], 'int'), secure($comment['comment_id'], 'int'))); if ($get_reaction->num_rows > 0) { $comment['i_react'] = true; $comment['i_reaction'] = $get_reaction->fetch_assoc()['reaction']; } } } /* return */ return $comment; } /** * delete_comment * * @param integer $comment_id * @return void */ public function delete_comment($comment_id) { global $db; /* (check|get) comment */ $comment = $this->get_comment($comment_id); if (!$comment) { _error(403); } /* check if viewer can manage comment [Delete] */ $comment['delete_comment'] = false; if ($this->_logged_in) { /* viewer is (admin|moderator) */ if ($this->_data['user_group'] < 3) { $comment['delete_comment'] = true; } /* viewer is the author of comment */ if ($this->_data['user_id'] == $comment['author_id']) { $comment['delete_comment'] = true; } /* viewer is the author of post */ if ($this->_data['user_id'] == $comment['post']['author_id']) { $comment['delete_comment'] = true; } /* viewer is the admin of the group of the post */ if ($comment['post']['in_group'] && $comment['post']['is_group_admin']) { $comment['delete_comment'] = true; } /* viewer is the admin of the event of the post */ if ($comment['post']['in_event'] && $comment['post']['is_event_admin']) { $comment['delete_comment'] = true; } } /* delete the comment */ if ($comment['delete_comment']) { /* delete the comment */ $db->query(sprintf("DELETE FROM posts_comments WHERE comment_id = %s", secure($comment_id, 'int'))); /* delete comment image from uploads folder */ delete_uploads_file($comment['image']); /* delete replies */ if ($comment['replies'] > 0) { $get_replies = $db->query(sprintf("SELECT image FROM posts_comments WHERE node_type = 'comment' AND node_id = %s", secure($comment_id, 'int'))); while ($reply = $get_replies->fetch_assoc()) { /* delete reply image from uploads folder */ delete_uploads_file($reply['image']); } $db->query(sprintf("DELETE FROM posts_comments WHERE node_type = 'comment' AND node_id = %s", secure($comment_id, 'int'))); } /* update comments counter */ switch ($comment['node_type']) { case 'post': $db->query(sprintf("UPDATE posts SET comments = IF(comments=0,0,comments-%s) WHERE post_id = %s", secure($comment['replies'] + 1, 'int'), secure($comment['node_id'], 'int'))); break; case 'photo': $db->query(sprintf("UPDATE posts_photos SET comments = IF(comments=0,0,comments-%s) WHERE photo_id = %s", secure($comment['replies'] + 1, 'int'), secure($comment['node_id'], 'int'))); break; case 'comment': $db->query(sprintf("UPDATE posts_comments SET replies = IF(replies=0,0,replies-1) WHERE comment_id = %s", secure($comment['node_id'], 'int'))); if ($comment['parent_comment']['node_type'] == "post") { $db->query(sprintf("UPDATE posts SET comments = IF(comments=0,0,comments-1) WHERE post_id = %s", secure($comment['parent_comment']['node_id'], 'int'))); } elseif ($comment['parent_comment']['node_type'] == "photo") { $db->query(sprintf("UPDATE posts_photos SET comments = IF(comments=0,0,comments-1) WHERE photo_id = %s", secure($comment['parent_comment']['node_id'], 'int'))); } break; } /* points balance */ $this->points_balance("delete", $comment['post']['author_id'], "post_comment"); $this->points_balance("delete", $comment['author_id'], "comment"); } } /** * edit_comment * * @param integer $comment_id * @param string $message * @param string $photo * @return array */ public function edit_comment($comment_id, $message, $photo) { global $db, $system; /* (check|get) comment */ $comment = $this->get_comment($comment_id); if (!$comment) { _error(403); } /* check if viewer can manage comment [Edit] */ $comment['edit_comment'] = false; if ($this->_logged_in) { /* viewer is (admin|moderator) */ if ($this->_data['user_group'] < 3) { $comment['edit_comment'] = true; } /* viewer is the author of comment */ if ($this->_data['user_id'] == $comment['author_id']) { $comment['edit_comment'] = true; } } if (!$comment['edit_comment']) { _error(400); } /* check post max length */ if ($system['max_comment_length'] > 0 && $this->_data['user_group'] >= 3) { if (strlen($message) >= $system['max_comment_length']) { modal("MESSAGE", __("Text Length Limit Reached"), __("Your message characters length is over the allowed limit") . " (" . $system['max_comment_length'] . " " . __("Characters") . ")"); } } /* update comment */ $comment['text'] = $message; $comment['image'] = (!is_empty($comment['image'])) ? $comment['image'] : $photo; $db->query(sprintf("UPDATE posts_comments SET text = %s, image = %s WHERE comment_id = %s", secure($comment['text']), secure($comment['image']), secure($comment_id, 'int'))); /* post mention notifications if any */ if ($comment['node_type'] == "comment") { $this->post_mentions($comment['text'], $comment['parent_comment']['node_id'], "reply_" . $comment['parent_comment']['node_type'], 'comment_' . $comment['comment_id'], [$comment['post']['author_id'], $comment['parent_comment']['author_id']]); } else { $this->post_mentions($comment['text'], $comment['node_id'], "comment_" . $comment['node_type'], 'comment_' . $comment['comment_id'], [$comment['post']['author_id']]); } /* parse text */ $comment['text_plain'] = htmlentities($comment['text'], ENT_QUOTES, 'utf-8'); $comment['text'] = $this->_parse(["text" => $comment['text_plain']]); /* return */ return $comment; } /** * react_comment * * @param integer $comment_id * @param string $reaction * @return void */ public function react_comment($comment_id, $reaction) { global $db, $date; /* check reation */ if (!in_array($reaction, ['like', 'love', 'haha', 'yay', 'wow', 'sad', 'angry'])) { _error(403); } /* (check|get) comment */ $comment = $this->get_comment($comment_id); if (!$comment) { _error(403); } /* check blocking */ if ($this->blocked($comment['author_id'])) { _error(403); } /* react the comment */ if ($comment['i_react']) { $db->query(sprintf("DELETE FROM posts_comments_reactions WHERE user_id = %s AND comment_id = %s", secure($this->_data['user_id'], 'int'), secure($comment_id, 'int'))); /* update comment reaction counter */ $reaction_field = "reaction_" . $comment['i_reaction'] . "_count"; $db->query(sprintf("UPDATE posts_comments SET $reaction_field = IF($reaction_field=0,0,$reaction_field-1) WHERE comment_id = %s", secure($comment_id, 'int'))); /* delete notification */ switch ($comment['node_type']) { case 'post': $this->delete_notification($comment['author_id'], 'react_' . $comment['i_reaction'], 'post_comment', $comment['node_id']); break; case 'photo': $this->delete_notification($comment['author_id'], 'react_' . $comment['i_reaction'], 'photo_comment', $comment['node_id']); break; case 'comment': $_node_type = ($comment['parent_comment']['node_type'] == "post") ? "post_reply" : "photo_reply"; $_node_url = $comment['parent_comment']['node_id']; $this->delete_notification($comment['author_id'], 'react_' . $comment['i_reaction'], $_node_type, $_node_url); break; } } $db->query(sprintf("INSERT INTO posts_comments_reactions (user_id, comment_id, reaction, reaction_time) VALUES (%s, %s, %s, %s)", secure($this->_data['user_id'], 'int'), secure($comment_id, 'int'), secure($reaction), secure($date))); /* update comment reaction counter */ $reaction_field = "reaction_" . $reaction . "_count"; $db->query(sprintf("UPDATE posts_comments SET $reaction_field = $reaction_field + 1 WHERE comment_id = %s", secure($comment_id, 'int'))); /* post notification */ switch ($comment['node_type']) { case 'post': $this->post_notification(['to_user_id' => $comment['author_id'], 'action' => 'react_' . $reaction, 'node_type' => 'post_comment', 'node_url' => $comment['node_id'], 'notify_id' => 'comment_' . $comment_id]); break; case 'photo': $this->post_notification(['to_user_id' => $comment['author_id'], 'action' => 'react_' . $reaction, 'node_type' => 'photo_comment', 'node_url' => $comment['node_id'], 'notify_id' => 'comment_' . $comment_id]); break; case 'comment': $_node_type = ($comment['parent_comment']['node_type'] == "post") ? "post_reply" : "photo_reply"; $_node_url = $comment['parent_comment']['node_id']; $this->post_notification(['to_user_id' => $comment['author_id'], 'action' => 'react_' . $reaction, 'node_type' => $_node_type, 'node_url' => $_node_url, 'notify_id' => 'comment_' . $comment_id]); break; } } /** * unreact_comment * * @param integer $comment_id * @param string $reaction * @return void */ public function unreact_comment($comment_id, $reaction) { global $db; /* check reation */ if (!in_array($reaction, ['like', 'love', 'haha', 'yay', 'wow', 'sad', 'angry'])) { _error(403); } /* (check|get) comment */ $comment = $this->get_comment($comment_id); if (!$comment) { _error(403); } /* check blocking */ if ($this->blocked($comment['author_id'])) { _error(403); } /* unreact the comment */ if ($comment['i_react']) { $db->query(sprintf("DELETE FROM posts_comments_reactions WHERE user_id = %s AND comment_id = %s", secure($this->_data['user_id'], 'int'), secure($comment_id, 'int'))); /* update comment reaction counter */ $reaction_field = "reaction_" . $reaction . "_count"; $db->query(sprintf("UPDATE posts_comments SET $reaction_field = IF($reaction_field=0,0,$reaction_field-1) WHERE comment_id = %s", secure($comment_id, 'int'))); /* delete notification */ switch ($comment['node_type']) { case 'post': $this->delete_notification($comment['author_id'], 'react_' . $reaction, 'post_comment', $comment['node_id']); break; case 'photo': $this->delete_notification($comment['author_id'], 'react_' . $reaction, 'photo_comment', $comment['node_id']); break; case 'comment': $_node_type = ($comment['parent_comment']['node_type'] == "post") ? "post_reply" : "photo_reply"; $_node_url = $comment['parent_comment']['node_id']; $this->delete_notification($comment['author_id'], 'react_' . $reaction, $_node_type, $_node_url); break; } } } /* ------------------------------- */ /* Photos & Albums */ /* ------------------------------- */ /** * get_photos * * @param integer $id * @param string $type * @param integer $offset * @param boolean $pass_check * @param boolean $get_pinned * @return array */ public function get_photos($id, $type = 'user', $offset = 0, $pass_check = true, $get_pinned = false) { global $db, $system; $photos = []; switch ($type) { case 'album': $offset *= $system['max_results_even']; if (!$pass_check) { /* check the album */ $album = $this->get_album($id, false); if (!$album) { return $photos; } } $get_photos = $db->query(sprintf("SELECT posts_photos.photo_id, posts_photos.source, posts_photos.blur, posts.user_id, posts.user_type, posts.privacy FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts_photos.album_id = %s AND posts.is_anonymous = '0' AND posts.is_paid = '0' AND (posts.pre_approved = '1' OR posts.has_approved = '1') ORDER BY posts_photos.photo_id DESC LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['max_results_even'], 'int', false))); if ($get_photos->num_rows > 0) { while ($photo = $get_photos->fetch_assoc()) { /* check the photo privacy */ if ($photo['privacy'] == "public" || $photo['privacy'] == "custom") { if ($album) { $photo['manage'] = $album['manage_album']; } $photos[] = $photo; } else { /* check the photo privacy */ if ($this->check_privacy($photo['privacy'], $photo['user_id'])) { if ($album) { $photo['manage'] = $album['manage_album']; } $photos[] = $photo; } } } } break; case 'user': /* get the target user's privacy */ $get_privacy = $db->query(sprintf("SELECT user_privacy_photos FROM users WHERE user_id = %s", secure($id, 'int'))); $privacy = $get_privacy->fetch_assoc(); /* check the target user's privacy */ if (!$this->check_privacy($privacy['user_privacy_photos'], $id)) { return $photos; } /* check manage photos */ $manage_photos = false; if ($this->_logged_in) { /* viewer is (admin|moderator) */ if ($this->_data['user_group'] < 3) { $manage_photos = true; } /* viewer is the author of photos */ if ($this->_data['user_id'] == $id) { $manage_photos = true; } } /* get all user photos (except photos from groups, events, anonymous posts & paid posts) */ $offset *= $system['min_results_even']; $order_statement = ($get_pinned) ? "posts_photos.pinned DESC, posts_photos.photo_id DESC" : "posts_photos.photo_id DESC"; $get_photos = $db->query(sprintf("SELECT posts_photos.photo_id, posts_photos.source, posts_photos.blur, posts_photos.pinned, posts.privacy FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.user_id = %s AND posts.user_type = 'user' AND posts.in_group = '0' AND posts.in_event = '0' AND posts.is_anonymous = '0' AND posts.is_paid = '0' AND (posts.pre_approved = '1' OR posts.has_approved = '1') ORDER BY $order_statement LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['min_results_even'], 'int', false))); if ($get_photos->num_rows > 0) { while ($photo = $get_photos->fetch_assoc()) { if ($this->check_privacy($photo['privacy'], $id)) { $photo['manage'] = $manage_photos; $photos[] = $photo; } } } break; case 'page': /* check manage photos */ $manage_photos = false; if ($this->_logged_in) { /* viewer is (admin|moderator) */ if ($this->_data['user_group'] < 3) { $manage_photos = true; } /* viewer is the author of photos */ if ($this->check_page_adminship($this->_data['user_id'], $id)) { $manage_photos = true; } } /* get all page photos */ $offset *= $system['min_results_even']; $get_photos = $db->query(sprintf("SELECT posts_photos.photo_id, posts_photos.source, posts_photos.blur FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.user_id = %s AND posts.user_type = 'page' AND posts.is_paid = '0' AND (posts.pre_approved = '1' OR posts.has_approved = '1') ORDER BY posts_photos.photo_id DESC LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['min_results_even'], 'int', false))); if ($get_photos->num_rows > 0) { while ($photo = $get_photos->fetch_assoc()) { $photo['manage'] = $manage_photos; $photos[] = $photo; } } break; case 'group': if (!$pass_check) { /* check if the viewer is group member (approved) */ if ($this->check_group_membership($this->_data['user_id'], $id) != "approved") { return $photos; } } /* check manage photos */ $manage_photos = false; if ($this->_logged_in) { /* viewer is (admin|moderator) */ if ($this->_data['user_group'] < 3) { $manage_photos = true; } /* viewer is the author of photos */ if ($this->check_group_adminship($this->_data['user_id'], $id)) { $manage_photos = true; } } /* get all group photos */ $offset *= $system['min_results_even']; $get_photos = $db->query(sprintf("SELECT posts_photos.photo_id, posts_photos.source, posts_photos.blur FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.group_id = %s AND posts.in_group = '1' AND posts.is_paid = '0' AND (posts.pre_approved = '1' OR posts.has_approved = '1') ORDER BY posts_photos.photo_id DESC LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['min_results_even'], 'int', false))); if ($get_photos->num_rows > 0) { while ($photo = $get_photos->fetch_assoc()) { $photo['manage'] = $manage_photos; $photos[] = $photo; } } break; case 'event': if (!$pass_check) { /* check if the viewer is event member (approved) */ if (!$this->check_event_membership($this->_data['user_id'], $id)) { return $photos; } } /* check manage photos */ $manage_photos = false; if ($this->_logged_in) { /* viewer is (admin|moderator) */ if ($this->_data['user_group'] < 3) { $manage_photos = true; } /* viewer is the author of photos */ if ($this->check_event_adminship($this->_data['user_id'], $id)) { $manage_photos = true; } } /* get all event photos */ $offset *= $system['min_results_even']; $get_photos = $db->query(sprintf("SELECT posts_photos.photo_id, posts_photos.source, posts_photos.blur FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.event_id = %s AND posts.in_event = '1' AND posts.is_paid = '0' AND (posts.pre_approved = '1' OR posts.has_approved = '1') ORDER BY posts_photos.photo_id DESC LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['min_results_even'], 'int', false))); if ($get_photos->num_rows > 0) { while ($photo = $get_photos->fetch_assoc()) { $photo['manage'] = $manage_photos; $photos[] = $photo; } } break; } return $photos; } /** * get_photos_count * * @param integer $node_id * @param string $node_type * @return integer */ public function get_photos_count($node_id, $node_type) { global $db; switch ($node_type) { case 'user': $get_photos = $db->query(sprintf("SELECT COUNT(*) as count FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.user_id = %s AND posts.user_type = 'user' AND posts.in_group = '0' AND posts.in_event = '0' AND (posts.pre_approved = '1' OR posts.has_approved = '1')", secure($node_id, 'int'))); break; case 'page': $get_photos = $db->query(sprintf("SELECT COUNT(*) as count FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.user_id = %s AND posts.user_type = 'page' AND (posts.pre_approved = '1' OR posts.has_approved = '1')", secure($node_id, 'int'))); break; case 'group': $get_photos = $db->query(sprintf("SELECT COUNT(*) as count FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.group_id = %s AND posts.in_group = '1' AND (posts.pre_approved = '1' OR posts.has_approved = '1')", secure($node_id, 'int'))); break; case 'event': $get_photos = $db->query(sprintf("SELECT COUNT(*) as count FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.event_id = %s AND posts.in_event = '1' AND (posts.pre_approved = '1' OR posts.has_approved = '1')", secure($node_id, 'int'))); break; default: _error(400); break; } if ($get_photos->num_rows > 0) { $count = $get_photos->fetch_assoc(); return $count['count']; } return 0; } /** * get_photo * * @param integer $photo_id * @param boolean $full_details * @param boolean $get_gallery * @param string $context * @return array */ public function get_photo($photo_id, $full_details = false, $get_gallery = false, $context = 'photos') { global $db, $system; /* get photo */ $get_photo = $db->query(sprintf("SELECT * FROM posts_photos WHERE photo_id = %s", secure($photo_id, 'int'))); if ($get_photo->num_rows == 0) { return false; } $photo = $get_photo->fetch_assoc(); /* get post */ $post = $this->_check_post($photo['post_id'], false, $full_details); if (!$post) { return false; } /* check if photo can be deleted */ if ($post['in_group']) { /* check if (cover|profile) photo */ $photo['can_delete'] = (($photo_id == $post['group_picture_id']) or ($photo_id == $post['group_cover_id'])) ? false : true; } elseif ($post['in_event']) { /* check if (cover) photo */ $photo['can_delete'] = (($photo_id == $post['event_cover_id'])) ? false : true; } elseif ($post['user_type'] == "user") { /* check if (cover|profile) photo */ $photo['can_delete'] = (($photo_id == $post['user_picture_id']) or ($photo_id == $post['user_cover_id'])) ? false : true; } elseif ($post['user_type'] == "page") { /* check if (cover|profile) photo */ $photo['can_delete'] = (($photo_id == $post['page_picture_id']) or ($photo_id == $post['page_cover_id'])) ? false : true; } /* check photo type [single|mutiple] */ $check_single = $db->query(sprintf("SELECT COUNT(*) as count FROM posts_photos WHERE post_id = %s", secure($photo['post_id'], 'int'))); $photo['is_single'] = ($check_single->fetch_assoc()['count'] > 1) ? false : true; /* get reactions */ if ($photo['is_single']) { /* [Case: 1] single photo => get (reactions) of post */ /* get reactions array */ $photo['reactions'] = $post['reactions']; /* get total reactions */ $photo['reactions_total_count'] = $post['reactions_total_count']; $photo['reactions_total_count_formatted'] = $post['reactions_total_count_formatted']; /* check if viewer [reacted] this post */ $photo['i_react'] = $post['i_react']; $photo['i_reaction'] = $post['i_reaction']; } else { /* [Case: 2] mutiple photo => get (reactions) of photo */ /* get reactions array */ $photo['reactions']['like'] = $photo['reaction_like_count']; $photo['reactions']['love'] = $photo['reaction_love_count']; $photo['reactions']['haha'] = $photo['reaction_haha_count']; $photo['reactions']['yay'] = $photo['reaction_yay_count']; $photo['reactions']['wow'] = $photo['reaction_wow_count']; $photo['reactions']['sad'] = $photo['reaction_sad_count']; $photo['reactions']['angry'] = $photo['reaction_angry_count']; arsort($photo['reactions']); /* get total reactions */ $photo['reactions_total_count'] = $photo['reaction_like_count'] + $photo['reaction_love_count'] + $photo['reaction_haha_count'] + $photo['reaction_yay_count'] + $photo['reaction_wow_count'] + $photo['reaction_sad_count'] + $photo['reaction_angry_count']; $photo['reactions_total_count_formatted'] = abbreviate_count($photo['reactions_total_count']); /* check if viewer [reacted] this photo */ $photo['i_react'] = false; if ($this->_logged_in) { /* reaction */ $get_reaction = $db->query(sprintf("SELECT reaction FROM posts_photos_reactions WHERE user_id = %s AND photo_id = %s", secure($this->_data['user_id'], 'int'), secure($photo['photo_id'], 'int'))); if ($get_reaction->num_rows > 0) { $photo['i_react'] = true; $photo['i_reaction'] = $get_reaction->fetch_assoc()['reaction']; } } } /* get full details (comments) */ if ($full_details) { if ($photo['is_single']) { /* [Case: 1] single photo => get (comments) of post */ /* get total comments */ $photo['comments'] = $post['comments']; $photo['comments_formatted'] = abbreviate_count($photo['comments']); /* get post comments */ if ($post['comments'] > 0) { $post['post_comments'] = $this->get_comments($post['post_id'], 0, true, true, $post); } } else { /* [Case: 2] mutiple photo => get (comments) of photo */ /* get photo comments */ if ($photo['comments'] > 0) { $photo['photo_comments'] = $this->get_comments($photo['photo_id'], 0, false, true, $post); } } } /* get gallery */ if ($get_gallery) { switch ($context) { case 'post': $get_post_photos = $db->query(sprintf("SELECT photo_id, source FROM posts_photos WHERE post_id = %s ORDER BY photo_id ASC", secure($post['post_id'], 'int'))); while ($post_photo = $get_post_photos->fetch_assoc()) { $post_photos[$post_photo['photo_id']] = $post_photo; } $photo['next'] = $post_photos[get_array_key($post_photos, $photo['photo_id'], 1)]; $photo['prev'] = $post_photos[get_array_key($post_photos, $photo['photo_id'], -1)]; break; case 'album': $get_album_photos = $db->query(sprintf("SELECT posts_photos.post_id, posts_photos.photo_id, posts_photos.source, posts.user_id, posts.privacy FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts_photos.album_id = %s", secure($photo['album_id'], 'int'))); while ($album_photo = $get_album_photos->fetch_assoc()) { /* check the photo privacy */ if ($album_photo['privacy'] == "public" || $album_photo['privacy'] == "custom") { $album_photos[$album_photo['photo_id']] = $album_photo; } else { /* check the photo privacy */ if ($this->check_privacy($album_photo['privacy'], $album_photo['user_id'])) { $album_photos[$album_photo['photo_id']] = $album_photo; } } } $photo['next'] = ($post['is_anonymous']) ? null : $album_photos[get_array_key($album_photos, $photo['photo_id'], -1)]; $photo['prev'] = ($post['is_anonymous']) ? null : $album_photos[get_array_key($album_photos, $photo['photo_id'], 1)]; /* check the next & prev photos posts (if paid or for subscribers) */ if ($photo['next']) { $next_post = $this->_check_post($photo['next']['post_id'], false, false); if ($next_post['needs_payment'] || $next_post['needs_subscription']) { $photo['next'] = null; } } if ($photo['prev']) { $prev_post = $this->_check_post($photo['prev']['post_id'], false, false); if ($prev_post['needs_payment'] || $prev_post['needs_subscription']) { $photo['prev'] = null; } } break; case 'photos': if ($post['in_group']) { $get_target_photos = $db->query(sprintf("SELECT posts_photos.post_id, posts_photos.photo_id, posts_photos.source, posts.user_id, posts.privacy FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.in_group = '1' AND posts.group_id = %s", secure($post['group_id'], 'int'))); } elseif ($post['in_event']) { $get_target_photos = $db->query(sprintf("SELECT posts_photos.post_id, posts_photos.photo_id, posts_photos.source, posts.user_id, posts.privacy FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.in_event = '1' AND posts.event_id = %s", secure($post['event_id'], 'int'))); } elseif ($post['user_type'] == "page") { $get_target_photos = $db->query(sprintf("SELECT posts_photos.post_id, posts_photos.photo_id, posts_photos.source, posts.user_id, posts.privacy FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.user_type = 'page' AND posts.user_id = %s", secure($post['user_id'], 'int'))); } elseif ($post['user_type'] == "user") { $get_target_photos = $db->query(sprintf("SELECT posts_photos.post_id, posts_photos.photo_id, posts_photos.source, posts.user_id, posts.privacy FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE posts.user_type = 'user' AND posts.user_id = %s", secure($post['user_id'], 'int'))); } while ($target_photo = $get_target_photos->fetch_assoc()) { /* check the photo privacy */ if ($target_photo['privacy'] == "public" || $target_photo['privacy'] == "custom") { $target_photos[$target_photo['photo_id']] = $target_photo; } else { /* check the photo privacy */ if ($this->check_privacy($target_photo['privacy'], $target_photo['user_id'])) { $target_photos[$target_photo['photo_id']] = $target_photo; } } } $photo['next'] = $target_photos[get_array_key($target_photos, $photo['photo_id'], -1)]; $photo['prev'] = $target_photos[get_array_key($target_photos, $photo['photo_id'], 1)]; /* check the next & prev photos posts (if paid or for subscribers) */ if ($photo['next']) { $next_post = $this->_check_post($photo['next']['post_id'], false, false); if ($next_post['needs_payment'] || $next_post['needs_subscription']) { $photo['next'] = null; } } if ($photo['prev']) { $prev_post = $this->_check_post($photo['prev']['post_id'], false, false); if ($prev_post['needs_payment'] || $prev_post['needs_subscription']) { $photo['prev'] = null; } } break; } } /* og-meta tags */ $photo['og_title'] = $post['post_author_name']; $photo['og_title'] .= ($post['text'] != "") ? " - " . $post['text'] : ""; $photo['og_description'] = $post['text']; $photo['og_image'] = $system['system_uploads'] . '/' . $photo['source']; /* return post array with photo */ $photo['post'] = $post; return $photo; } /** * delete_photo * * @param integer $photo_id * @return void */ public function delete_photo($photo_id) { global $db, $system; /* (check|get) photo */ $photo = $this->get_photo($photo_id); if (!$photo) { _error(403); } $post = $photo['post']; /* check if viewer can manage post */ if (!$post['manage_post']) { _error(403); } /* check if photo can be deleted */ if (!$photo['can_delete']) { throw new Exception(__("This photo can't be deleted as it maybe your current profile image or cover")); } /* delete the photo */ $db->query(sprintf("DELETE FROM posts_photos WHERE photo_id = %s", secure($photo_id, 'int'))); /* delete photo from uploads folder */ delete_uploads_file($photo['source']); } /** * pin_photo * * @param integer $photo_id * @return void */ public function pin_photo($photo_id) { global $db, $system; /* (check|get) photo */ $photo = $this->get_photo($photo_id); if (!$photo) { _error(403); } $post = $photo['post']; /* check if viewer can manage post */ if (!$post['manage_post']) { _error(403); } /* pin the photo */ $db->query(sprintf("UPDATE posts_photos SET pinned = '1' WHERE photo_id = %s", secure($photo_id, 'int'))); } /** * unpin_photo * * @param integer $photo_id * @return void */ public function unpin_photo($photo_id) { global $db, $system; /* (check|get) photo */ $photo = $this->get_photo($photo_id); if (!$photo) { _error(403); } $post = $photo['post']; /* check if viewer can manage post */ if (!$post['manage_post']) { _error(403); } /* unpin the photo */ $db->query(sprintf("UPDATE posts_photos SET pinned = '0' WHERE photo_id = %s", secure($photo_id, 'int'))); } /** * react_photo * * @param integer $photo_id * @param string $reaction * @return void */ public function react_photo($photo_id, $reaction) { global $db, $date; /* check reation */ if (!in_array($reaction, ['like', 'love', 'haha', 'yay', 'wow', 'sad', 'angry'])) { _error(403); } /* (check|get) photo */ $photo = $this->get_photo($photo_id); if (!$photo) { _error(403); } $post = $photo['post']; /* check blocking */ if ($post['user_type'] == "user" && $this->blocked($post['author_id'])) { _error(403); } /* reaction the post */ if ($photo['i_react']) { /* remove any previous reaction */ $db->query(sprintf("DELETE FROM posts_photos_reactions WHERE user_id = %s AND photo_id = %s", secure($this->_data['user_id'], 'int'), secure($photo_id, 'int'))); /* update photo reaction counter */ $reaction_field = "reaction_" . $photo['i_reaction'] . "_count"; $db->query(sprintf("UPDATE posts_photos SET $reaction_field = IF($reaction_field=0,0,$reaction_field-1) WHERE photo_id = %s", secure($photo_id, 'int'))); /* delete notification */ $this->delete_notification($post['author_id'], 'react_' . $photo['i_reaction'], 'photo', $photo_id); } $db->query(sprintf("INSERT INTO posts_photos_reactions (user_id, photo_id, reaction, reaction_time) VALUES (%s, %s, %s, %s)", secure($this->_data['user_id'], 'int'), secure($photo_id, 'int'), secure($reaction), secure($date))); $reaction_id = $db->insert_id; /* update photo reaction counter */ $reaction_field = "reaction_" . $reaction . "_count"; $db->query(sprintf("UPDATE posts_photos SET $reaction_field = $reaction_field + 1 WHERE photo_id = %s", secure($photo_id, 'int'))); /* post notification */ $this->post_notification(['to_user_id' => $post['author_id'], 'action' => 'react_' . $reaction, 'node_type' => 'photo', 'node_url' => $photo_id]); /* points balance */ $this->points_balance("add", $this->_data['user_id'], "posts_photos_reactions", $reaction_id); } /** * unreact_photo * * @param integer $photo_id * @param string $reaction * @return void */ public function unreact_photo($photo_id, $reaction) { global $db; /* (check|get) photo */ $photo = $this->get_photo($photo_id); if (!$photo) { _error(403); } $post = $photo['post']; /* unreact the photo */ $db->query(sprintf("DELETE FROM posts_photos_reactions WHERE user_id = %s AND photo_id = %s", secure($this->_data['user_id'], 'int'), secure($photo_id, 'int'))); /* update photo reaction counter */ $reaction_field = "reaction_" . $photo['i_reaction'] . "_count"; $db->query(sprintf("UPDATE posts_photos SET $reaction_field = IF($reaction_field=0,0,$reaction_field-1) WHERE photo_id = %s", secure($photo_id, 'int'))); /* delete notification */ $this->delete_notification($post['author_id'], 'react_' . $reaction, 'photo', $photo_id); /* points balance */ $this->points_balance("delete", $this->_data['user_id'], "posts_photos_reactions"); } /** * get_albums * * @param integer $user_id * @param string $type * @param integer $offset * @return array */ public function get_albums($id, $type = 'user', $offset = 0) { global $db, $system; /* initialize vars */ $albums = []; $offset *= $system['max_results_even']; switch ($type) { case 'user': $get_albums = $db->query(sprintf("SELECT album_id FROM posts_photos_albums WHERE user_type = 'user' AND user_id = %s AND in_group = '0' AND in_event = '0' LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['max_results_even'], 'int', false))); break; case 'page': $get_albums = $db->query(sprintf("SELECT album_id FROM posts_photos_albums WHERE user_type = 'page' AND user_id = %s LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['max_results_even'], 'int', false))); break; case 'group': $get_albums = $db->query(sprintf("SELECT album_id FROM posts_photos_albums WHERE in_group = '1' AND group_id = %s LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['max_results_even'], 'int', false))); break; case 'event': $get_albums = $db->query(sprintf("SELECT album_id FROM posts_photos_albums WHERE in_event = '1' AND event_id = %s LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['max_results_even'], 'int', false))); break; } if ($get_albums->num_rows > 0) { while ($album = $get_albums->fetch_assoc()) { $album = $this->get_album($album['album_id'], false); /* $full_details = false */ if ($album) { $albums[] = $album; } } } return $albums; } /** * get_album * * @param integer $album_id * @param boolean $full_details * @return array */ public function get_album($album_id, $full_details = true) { global $db, $system; $get_album = $db->query(sprintf("SELECT posts_photos_albums.*, users.user_name, users.user_album_pictures, users.user_album_covers, users.user_album_timeline, pages.page_id, pages.page_name, pages.page_admin, pages.page_album_pictures, pages.page_album_covers, pages.page_album_timeline, `groups`.group_name, `groups`.group_admin, `groups`.group_album_pictures, `groups`.group_album_covers, `groups`.group_album_timeline, `events`.event_admin, `events`.event_album_covers, `events`.event_album_timeline FROM posts_photos_albums LEFT JOIN users ON posts_photos_albums.user_id = users.user_id AND posts_photos_albums.user_type = 'user' LEFT JOIN pages ON posts_photos_albums.user_id = pages.page_id AND posts_photos_albums.user_type = 'page' LEFT JOIN `groups` ON posts_photos_albums.in_group = '1' AND posts_photos_albums.group_id = `groups`.group_id LEFT JOIN `events` ON posts_photos_albums.in_event = '1' AND posts_photos_albums.event_id = `events`.event_id WHERE NOT (users.user_name <=> NULL AND pages.page_name <=> NULL) AND posts_photos_albums.album_id = %s", secure($album_id, 'int'))); if ($get_album->num_rows == 0) { return false; } $album = $get_album->fetch_assoc(); /* get the author */ $album['author_id'] = ($album['user_type'] == "page") ? $album['page_admin'] : $album['user_id']; /* check the album privacy */ /* if album in group & (the group is public || the viewer approved member of this group) => pass privacy check */ if ($album['in_group'] && ($album['group_privacy'] == 'public' || $this->check_group_membership($this->_data['user_id'], $album['group_id']) == 'approved')) { $pass_privacy_check = true; } /* if album in event & (the event is public || the viewer member of this event) => pass privacy check */ if ($album['in_event'] && ($album['event_privacy'] == 'public' || $this->check_event_membership($this->_data['user_id'], $album['event_id']))) { $pass_privacy_check = true; } if (!$pass_privacy_check) { if (!$this->check_privacy($album['privacy'], $album['author_id'])) { return false; } } /* get album path */ if ($album['in_group']) { $album['path'] = 'groups/' . $album['group_name']; /* check if (cover|profile|timeline) album */ $album['can_delete'] = (($album_id == $album['group_album_pictures']) or ($album_id == $album['group_album_covers']) or ($album_id == $album['group_album_timeline'])) ? false : true; } elseif ($album['in_event']) { $album['path'] = 'events/' . $album['event_id']; /* check if (cover|profile|timeline) album */ $album['can_delete'] = (($album_id == $album['event_album_pictures']) or ($album_id == $album['event_album_covers']) or ($album_id == $album['event_album_timeline'])) ? false : true; } elseif ($album['user_type'] == "user") { $album['path'] = $album['user_name']; /* check if (cover|profile|timeline) album */ $album['can_delete'] = (($album_id == $album['user_album_pictures']) or ($album_id == $album['user_album_covers']) or ($album_id == $album['user_album_timeline'])) ? false : true; } elseif ($album['user_type'] == "page") { $album['path'] = 'pages/' . $album['page_name']; /* check if (cover|profile|timeline) album */ $album['can_delete'] = (($album_id == $album['user_album_timeline']) or ($album_id == $album['page_album_covers']) or ($album_id == $album['page_album_timeline'])) ? false : true; } /* get album cover photo */ $where_statement = ($album['user_type'] == "user" && !$album['in_group'] && !$album['in_event']) ? "posts.privacy = 'public' AND" : ''; $get_cover = $db->query(sprintf("SELECT source, blur FROM posts_photos INNER JOIN posts ON posts_photos.post_id = posts.post_id WHERE " . $where_statement . " posts_photos.album_id = %s AND posts.is_paid = '0' ORDER BY photo_id DESC LIMIT 1", secure($album_id, 'int'))); if ($get_cover->num_rows == 0) { $album['cover']['source'] = $system['system_url'] . '/content/themes/' . $system['theme'] . '/images/blank_album.png'; $album['cover']['blur'] = 0; } else { $cover = $get_cover->fetch_assoc(); $album['cover']['source'] = $system['system_uploads'] . '/' . $cover['source']; $album['cover']['blur'] = $cover['blur']; } /* get album total photos count */ $get_album_photos_count = $db->query(sprintf("SELECT COUNT(*) as count FROM posts_photos WHERE album_id = %s", secure($album_id, 'int'))); $album['photos_count'] = $get_album_photos_count->fetch_assoc()['count']; /* check if viewer can manage album [Edit|Update|Delete] */ $album['is_page_admin'] = $this->check_page_adminship($this->_data['user_id'], $album['page_id']); $album['is_group_admin'] = $this->check_group_adminship($this->_data['user_id'], $album['group_id']); $album['is_event_admin'] = $this->check_event_adminship($this->_data['user_id'], $album['event_id']); /* check if viewer can manage album [Edit|Update|Delete] */ $album['manage_album'] = false; if ($this->_logged_in) { /* viewer is (admin|moderator) */ if ($this->_data['user_group'] < 3) { $album['manage_album'] = true; } /* viewer is the author of post */ if ($this->_data['user_id'] == $album['author_id']) { $album['manage_album'] = true; } /* viewer is the admin of the page */ if ($album['user_type'] == "page" && $album['is_page_admin']) { $album['manage_album'] = true; } /* viewer is the admin of the group */ if ($album['in_group'] && $album['is_group_admin']) { $album['manage_album'] = true; } /* viewer is the admin of the event */ if ($album['in_event'] && $album['is_event_admin']) { $album['manage_album'] = true; } } /* get album photos */ if ($full_details) { $album['photos'] = $this->get_photos($album_id, 'album'); } return $album; } /** * delete_album * * @param integer $album_id * @return void */ public function delete_album($album_id) { global $db, $system; /* (check|get) album */ $album = $this->get_album($album_id, false); if (!$album) { _error(403); } /* check if viewer can manage album */ if (!$album['manage_album']) { _error(403); } /* check if album can be deleted */ if (!$album['can_delete']) { throw new Exception(__("This album can't be deleted")); } /* delete the album */ $db->query(sprintf("DELETE FROM posts_photos_albums WHERE album_id = %s", secure($album_id, 'int'))); /* delete all album photos */ $db->query(sprintf("DELETE FROM posts_photos WHERE album_id = %s", secure($album_id, 'int'))); /* retrun path */ $path = $system['system_url'] . "/" . $album['path'] . "/albums"; return $path; } /** * edit_album * * @param integer $album_id * @param string $title * @return void */ public function edit_album($album_id, $title) { global $db; /* (check|get) album */ $album = $this->get_album($album_id, false); if (!$album) { _error(400); } /* check if viewer can manage album */ if (!$album['manage_album']) { _error(400); } /* validate all fields */ if (is_empty($title)) { throw new Exception(__("You must fill in all of the fields")); } /* edit the album */ $db->query(sprintf("UPDATE posts_photos_albums SET title = %s WHERE album_id = %s", secure($title), secure($album_id, 'int'))); } /** * add_photos * * @param array $args * @return array */ public function add_album_photos($args = []) { global $db, $system, $date; /* (check|get) album */ $album = $this->get_album($args['album_id'], false); if (!$album) { _error(400); } /* check if viewer can manage album */ if (!$album['manage_album']) { _error(400); } /* check user_id */ $user_id = ($album['user_type'] == "page") ? $album['page_id'] : $album['user_id']; /* check privacy */ if ($album['in_group'] || $album['in_event']) { $args['privacy'] = 'custom'; } elseif ($album['user_type'] == "page") { $args['privacy'] = 'public'; } else { if (!in_array($args['privacy'], ['me', 'friends', 'public'])) { $args['privacy'] = 'public'; } } /* post feeling */ $post['feeling_action'] = ''; $post['feeling_value'] = ''; $post['feeling_icon'] = ''; if (!is_empty($args['feeling_action']) && !is_empty($args['feeling_value'])) { if ($args['feeling_action'] != "Feeling") { $_feeling_icon = get_feeling_icon($args['feeling_action'], get_feelings()); } else { $_feeling_icon = get_feeling_icon($args['feeling_value'], get_feelings_types()); } if ($_feeling_icon) { $post['feeling_action'] = $args['feeling_action']; $post['feeling_value'] = $args['feeling_value']; $post['feeling_icon'] = $_feeling_icon; } } /* insert the post */ $db->query(sprintf("INSERT INTO posts (user_id, user_type, in_group, group_id, in_event, event_id, post_type, time, location, privacy, text, feeling_action, feeling_value) VALUES (%s, %s, %s, %s, %s, %s, 'album', %s, %s, %s, %s, %s, %s)", secure($user_id, 'int'), secure($album['user_type']), secure($album['in_group']), secure($album['group_id'], 'int'), secure($album['in_event']), secure($album['event_id'], 'int'), secure($date), secure($args['location']), secure($args['privacy']), secure($args['message']), secure($post['feeling_action']), secure($post['feeling_value']))); $post_id = $db->insert_id; /* insert new photos */ foreach ($args['photos'] as $photo) { $db->query(sprintf("INSERT INTO posts_photos (post_id, album_id, source, blur) VALUES (%s, %s, %s, %s)", secure($post_id, 'int'), secure($args['album_id'], 'int'), secure($photo['source']), secure($photo['blur']))); } /* post mention notifications */ $this->post_mentions($args['message'], $post_id); return $post_id; } /* ------------------------------- */ /* Videos */ /* ------------------------------- */ /** * get_videos * * @param integer $id * @param string $type * @param integer $offset * @return array */ public function get_videos($id, $type = 'user', $offset = 0) { global $db, $system; $videos = []; switch ($type) { case 'user': /* get all user videos (except videos from groups or events) */ $offset *= $system['min_results_even']; $get_videos = $db->query(sprintf("SELECT posts_videos.*, posts.privacy FROM posts_videos INNER JOIN posts ON posts_videos.post_id = posts.post_id WHERE posts.user_id = %s AND posts.user_type = 'user' AND posts.in_group = '0' AND posts.in_event = '0' AND (posts.pre_approved = '1' OR posts.has_approved = '1') ORDER BY posts_videos.video_id DESC LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['min_results_even'], 'int', false))); if ($get_videos->num_rows > 0) { while ($video = $get_videos->fetch_assoc()) { if ($this->check_privacy($video['privacy'], $id)) { $videos[] = $video; } } } break; case 'page': $offset *= $system['min_results_even']; $get_videos = $db->query(sprintf("SELECT posts_videos.* FROM posts_videos INNER JOIN posts ON posts_videos.post_id = posts.post_id WHERE posts.user_id = %s AND posts.user_type = 'page' ORDER BY posts_videos.video_id DESC LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['min_results_even'], 'int', false))); if ($get_videos->num_rows > 0) { while ($video = $get_videos->fetch_assoc()) { $videos[] = $video; } } break; case 'group': /* check if the viewer is group member (approved) */ if ($this->check_group_membership($this->_data['user_id'], $id) != "approved") { return $videos; } $offset *= $system['min_results_even']; $get_videos = $db->query(sprintf("SELECT posts_videos.* FROM posts_videos INNER JOIN posts ON posts_videos.post_id = posts.post_id WHERE posts.group_id = %s AND posts.in_group = '1' ORDER BY posts_videos.video_id DESC LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['min_results_even'], 'int', false))); if ($get_videos->num_rows > 0) { while ($video = $get_videos->fetch_assoc()) { $videos[] = $video; } } break; case 'event': /* check if the viewer is event member (approved) */ if (!$this->check_event_membership($this->_data['user_id'], $id)) { return $videos; } $offset *= $system['min_results_even']; $get_videos = $db->query(sprintf("SELECT posts_videos.* FROM posts_videos INNER JOIN posts ON posts_videos.post_id = posts.post_id WHERE posts.event_id = %s AND posts.in_event = '1' ORDER BY posts_videos.video_id DESC LIMIT %s, %s", secure($id, 'int'), secure($offset, 'int', false), secure($system['min_results_even'], 'int', false))); if ($get_videos->num_rows > 0) { while ($video = $get_videos->fetch_assoc()) { $videos[] = $video; } } break; } return $videos; } /** * get_videos_count * * @param integer $node_id * @param string $node_type * @return integer */ public function get_videos_count($node_id, $node_type) { global $db; switch ($node_type) { case 'user': $get_videos = $db->query(sprintf("SELECT COUNT(*) as count FROM posts_videos INNER JOIN posts ON posts_videos.post_id = posts.post_id WHERE posts.user_id = %s AND posts.user_type = 'user' AND posts.in_group = '0' AND posts.in_event = '0' AND (posts.pre_approved = '1' OR posts.has_approved = '1')", secure($node_id, 'int'))); break; case 'page': $get_videos = $db->query(sprintf("SELECT COUNT(*) as count FROM posts_videos INNER JOIN posts ON posts_videos.post_id = posts.post_id WHERE posts.user_id = %s AND posts.user_type = 'page' AND (posts.pre_approved = '1' OR posts.has_approved = '1')", secure($node_id, 'int'))); break; case 'group': $get_videos = $db->query(sprintf("SELECT COUNT(*) as count FROM posts_videos INNER JOIN posts ON posts_videos.pos------------------------ */ /* Invitations */ /* ------------------------------- */ /** * get_invitation_codes_details * * @return array */ public function get_invitation_codes_details() { global $db; $codes = []; $get_codes = $db->query(sprintf('SELECT invitation_codes.*, users.user_id, users.user_name, users.user_firstname, users.user_lastname, users.user_gender, users.user_picture FROM invitation_codes LEFT JOIN users ON invitation_codes.used_by = users.user_id WHERE invitation_codes.created_by = %s', secure($this->_data['user_id'], 'int'))); if ($get_codes->num_rows > 0) { while ($code = $get_codes->fetch_assoc()) { if ($code['used']) { $code['user_picture'] = get_picture($code['user_picture'], $code['user_gender']); } $codes[] = $code; } } return $codes; } /** * get_invitation_codes_stats * * @return string */ public function get_invitation_codes_stats() { global $db, $system; $get_generated_codes = $db->query(sprintf("SELECT COUNT(*) as count FROM invitation_codes WHERE created_by = %s AND created_date >= DATE_SUB(NOW(),INTERVAL 1 %s)", secure($this->_data['user_id'], 'int'), strtoupper($system['invitation_expire_period']))); $generated_codes = $get_generated_codes->fetch_assoc()['count']; $available_codes = $system['invitation_user_limit'] - $generated_codes; $get_used_codes = $db->query(sprintf("SELECT COUNT(*) as count FROM invitation_codes WHERE created_by = %s AND created_date >= DATE_SUB(NOW(),INTERVAL 1 %s) AND used = '1'", secure($this->_data['user_id'], 'int'), strtoupper($system['invitation_expire_period']))); $used_codes = $get_used_codes->fetch_assoc()['count']; return ["available" => $available_codes, "generated" => $generated_codes, "used" => $used_codes]; } /** * check_user_invitation_codes * * @return void */ public function can_generate_invitation_code() { global $db, $system; if ($this->_data['can_invite_users']) { if ($system['invitation_user_limit'] == 0) { return true; } $check_limit = $db->query(sprintf("SELECT COUNT(*) as count FROM invitation_codes WHERE created_by = %s AND created_date >= DATE_SUB(NOW(),INTERVAL 1 %s)", secure($this->_data['user_id'], 'int'), strtoupper($system['invitation_expire_period']))); if ($check_limit->fetch_assoc()['count'] < $system['invitation_user_limit']) { return true; } } return false; } /** * get_invitation_code * * @return string */ public function generate_invitation_code() { global $db, $system, $date; /* check invitation enabled */ if (!$system['invitation_enabled']) { throw new Exception(__("The invitation system has been disabled by the admin")); } /* check invitation permission */ if (!$this->_data['can_invite_users']) { throw new Exception(__("You don't have the permission to do this")); } /* check if user can generate new code */ if (!$this->can_generate_invitation_code()) { throw new Exception(__("You have reached the maximum number of invitation codes")); } $code = get_hash_key(); $db->query(sprintf("INSERT INTO invitation_codes (code, created_by, created_date) VALUES (%s, %s, %s)", secure($code), secure($this->_data['user_id'], "int"), secure($date))); return $code; } /** * check_invitation_code ✅ * * @param string $code * @return boolean * */ public function check_invitation_code($code) { global $db; $query = $db->query(sprintf("SELECT COUNT(*) as count FROM invitation_codes WHERE code = %s AND used = '0'", secure($code))); if ($query->fetch_assoc()['count'] > 0) { return true; } return false; } /** * update_invitation_code * * @param string $code * @param string $user_id * @return void */ public function update_invitation_code($code, $user_id) { global $db, $date; $db->query(sprintf("UPDATE invitation_codes SET used = '1', used_by = %s, used_date = %s WHERE code = %s", secure($user_id, "int"), secure($date), secure($code))); } /** * send_invitation_email * * @param string $email * @param string $code * @return void */ public function send_invitation_email($email, $code) { global $db, $system, $date; /* check invitation enabled */ if (!$system['invitation_enabled']) { throw new Exception(__("The invitation system has been disabled by the admin")); } /* check invitation permission */ if (!$this->_data['can_invite_users']) { throw new Exception(__("You don't have the permission to do this")); } /* check invitation code */ if (!$this->check_invitation_code($code)) { throw new Exception(__("This invitation code is expired or invalid")); } /* check email */ if (!valid_email($email)) { throw new Exception(__("Please enter a valid email address")); } if ($this->check_email($email)) { throw new Exception(__("Sorry, it looks like") . " " . $email . " " . __("belongs to an existing account")); } /* check if viewer already invited this email before */ $check_invitation_log = $db->query(sprintf("SELECT COUNT(*) as count FROM users_invitations WHERE email_phone = %s", secure($email))); if ($check_invitation_log->fetch_assoc()['count'] > 0) { throw new Exception(__("You already invited this email before")); } /* prepare invitation email */ $subject = html_entity_decode($this->_data['name'], ENT_QUOTES) . " " . __("Invite you to join") . " " . html_entity_decode(__($system['system_title']), ENT_QUOTES); $body = get_email_template("invitation_user_email", $subject, ["code" => $code]); /* send email */ if (!_email($email, $subject, $body['html'], $body['plain'])) { throw new Exception(__("Invitation email could not be sent")); } /* add to log */ $db->query(sprintf("INSERT INTO users_invitations (user_id, email_phone, invitation_date) VALUES (%s, %s, %s)", secure($this->_data['user_id'], 'int'), secure($email), secure($date))); } /** * send_invitation_sms * * @param string $phone * @param string $code * @return void */ public function send_invitation_sms($phone, $code) { global $db, $system, $date; /* check invitation enabled */ if (!$system['invitation_enabled']) { throw new Exception(__("The invitation system has been disabled by the admin")); } /* check invitation permission */ if (!$this->_data['can_invite_users']) { throw new Exception(__("You don't have the permission to do this")); } /* check invitation code */ if (!$this->check_invitation_code($code)) { throw new Exception(__("This invitation code is expired or invalid")); } /* check phone */ if (is_empty($phone)) { throw new Exception(__("Please enter a valid phone number")); } if ($this->check_phone($phone)) { throw new Exception(__("Sorry, it looks like") . " " . $phone . " " . __("belongs to an existing account")); } /* check if viewer already invited this phone before */ $check_invitation_log = $db->query(sprintf("SELECT COUNT(*) as count FROM users_invitations WHERE email_phone = %s", secure($phone))); if ($check_invitation_log->fetch_assoc()['count'] > 0) { throw new Exception(__("You already invited this phone number before")); } /* prepare activation SMS */ $message = $this->_data['name'] . " " . __("Invite you to join") . " " . __($system['system_title']) . " " . $system['system_url'] . "/?ref=" . $this->_data['user_name'] . "&invitation_code=" . $code; /* send SMS */ if (!sms_send($phone, $message)) { throw new Exception(__("Invitation SMS could not be sent")); } /* add to log */ $db->query(sprintf("INSERT INTO users_invitations (user_id, email_phone, invitation_date) VALUES (%s, %s, %s)", secure($this->_data['user_id'], 'int'), secure($phone), secure($date))); } /* ------------------------------- */ /* User Settings */ /* ------------------------------- */ /** * settings * * @param string $edit * @param array $args * @return void */ public function settings($edit, $args) { global $db, $system; switch ($edit) { case 'account': /* validate current password (MD5 check for versions < v2.5) */ if (md5($args['password']) != $this->_data['user_password'] && !password_verify($args['password'], $this->_data['user_password'])) { throw new Exception(__("Your current password is incorrect")); } /* validate email */ if ($args['email'] != $this->_data['user_email']) { $this->activation_email_reset($args['email']); } /* validate phone */ if (isset($args['phone']) && $args['phone'] != $this->_data['user_phone']) { $this->activation_phone_reset($args['phone']); } /* validate username */ if (!$system['disable_username_changes']) { if (strtolower($args['username']) != strtolower($this->_data['user_name'])) { if (!valid_username($args['username'])) { throw new Exception(__("Please enter a valid username (a-z0-9_.) with minimum 3 characters long")); } if ($this->reserved_username($args['username'])) { throw new Exception(__("You can't use") . " " . $args['username'] . " " . __("as username")); } if ($this->check_username($args['username'])) { throw new Exception(__("Sorry, it looks like") . " " . $args['username'] . " " . __("belongs to an existing account")); } /* update user */ $db->query(sprintf("UPDATE users SET user_name = %s WHERE user_id = %s", secure($args['username']), secure($this->_data['user_id'], 'int'))); /* verification badge */ if ($this->_data['user_verified']) { $db->query(sprintf("UPDATE users SET user_verified = '0' WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); } } } break; case 'basic': if (!$system['show_usernames_enabled']) { /* validate firstname */ if (is_empty($args['firstname'])) { throw new Exception(__("You must enter first name")); } if (!valid_name($args['firstname'])) { throw new Exception(__("First name contains invalid characters")); } if (strlen($args['firstname']) < $system['name_min_length']) { throw new Exception(__("First name must be at least") . " " . $system['name_min_length'] . " " . __("characters long. Please try another")); } /* validate lastname */ if (is_empty($args['lastname'])) { throw new Exception(__("You must enter last name")); } if (!valid_name($args['lastname'])) { throw new Exception(__("Last name contains invalid characters")); } if (strlen($args['lastname']) < $system['name_min_length']) { throw new Exception(__("Last name must be at least") . " " . $system['name_min_length'] . " " . __("characters long. Please try another")); } } else { $args['firstname'] = $this->_data['user_firstname']; $args['lastname'] = $this->_data['user_lastname']; } /* validate gender */ $args['gender'] = ($system['genders_disabled']) ? 1 : $args['gender']; if (!$system['genders_disabled'] && !$this->check_gender($args['gender'])) { throw new Exception(__("Please select a valid gender")); } /* validate country */ if ($args['country'] == "none") { throw new Exception(__("You must select valid country")); } else { if (!$this->check_country($args['country'])) { throw new Exception(__("You must select valid country")); } } /* validate birthdate */ if ($args['birth_month'] == "none" && $args['birth_day'] == "none" && $args['birth_year'] == "none") { $args['birth_date'] = 'null'; } else { if (!in_array($args['birth_month'], range(1, 12))) { throw new Exception(__("Please select a valid birth month")); } if (!in_array($args['birth_day'], range(1, 31))) { throw new Exception(__("Please select a valid birth day")); } if (!in_array($args['birth_year'], range(1905, 2015))) { throw new Exception(__("Please select a valid birth year")); } $args['birth_date'] = $args['birth_year'] . '-' . $args['birth_month'] . '-' . $args['birth_day']; } /* validate relationship */ if (!isset($args['relationship']) || $args['relationship'] == "none") { $args['relationship'] = 'null'; } else { $relationships = ['single', 'relationship', 'married', "complicated", 'separated', 'divorced', 'widowed']; if (!in_array($args['relationship'], $relationships)) { throw new Exception(__("Please select a valid relationship")); } } /* validate website */ if (!is_empty($args['website'])) { if (!valid_url($args['website'])) { throw new Exception(__("Please enter a valid website")); } } else { $args['website'] = 'null'; } /* set custom fields */ $this->set_custom_fields($args, "user", "settings", $this->_data['user_id']); /* update user */ $db->query(sprintf("UPDATE users SET user_firstname = %s, user_lastname = %s, user_gender = %s, user_country = %s, user_birthdate = %s, user_relationship = %s, user_biography = %s, user_website = %s WHERE user_id = %s", secure($args['firstname']), secure($args['lastname']), secure($args['gender']), secure($args['country'], 'int'), secure($args['birth_date']), secure($args['relationship']), secure($args['biography']), secure($args['website']), secure($this->_data['user_id'], 'int'))); /* verification badge */ if ($this->_data['user_verified'] && ($this->_data['user_firstname'] != $args['firstname'] || $this->_data['user_lastname'] != $args['lastname'])) { $db->query(sprintf("UPDATE users SET user_verified = '0' WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); } break; case 'work': /* validate work website */ if (!is_empty($args['work_url'])) { /* check if contains https:// or http:// if not add it */ if (!preg_match("~^(?:f|ht)tps?://~i", $args['work_url'])) { $args['work_url'] = "https://" . $args['work_url']; } if (!valid_url($args['work_url'])) { throw new Exception(__("Please enter a valid work website")); } } else { $args['work_url'] = 'null'; } /* set custom fields */ $this->set_custom_fields($args, "user", "settings", $this->_data['user_id']); /* update user */ $db->query(sprintf("UPDATE users SET user_work_title = %s, user_work_place = %s, user_work_url = %s WHERE user_id = %s", secure($args['work_title']), secure($args['work_place']), secure($args['work_url']), secure($this->_data['user_id'], 'int'))); break; case 'location': /* set custom fields */ $this->set_custom_fields($args, "user", "settings", $this->_data['user_id']); /* update user */ $db->query(sprintf("UPDATE users SET user_current_city = %s, user_hometown = %s WHERE user_id = %s", secure($args['city']), secure($args['hometown']), secure($this->_data['user_id'], 'int'))); break; case 'education': /* set custom fields */ $this->set_custom_fields($args, "user", "settings", $this->_data['user_id']); /* update user */ $db->query(sprintf("UPDATE users SET user_edu_major = %s, user_edu_school = %s, user_edu_class = %s WHERE user_id = %s", secure($args['edu_major']), secure($args['edu_school']), secure($args['edu_class']), secure($this->_data['user_id'], 'int'))); break; case 'other': /* set custom fields */ $this->set_custom_fields($args, "user", "settings", $this->_data['user_id']); break; case 'social': /* validate facebook */ if (!is_empty($args['facebook']) && !valid_url($args['facebook'])) { throw new Exception(__("Please enter a valid Facebook Profile URL")); } /* validate twitter */ if (!is_empty($args['twitter']) && !valid_url($args['twitter'])) { throw new Exception(__("Please enter a valid Twitter Profile URL")); } /* validate youtube */ if (!is_empty($args['youtube']) && !valid_url($args['youtube'])) { throw new Exception(__("Please enter a valid YouTube Profile URL")); } /* validate instagram */ if (!is_empty($args['instagram']) && !valid_url($args['instagram'])) { throw new Exception(__("Please enter a valid Instagram Profile URL")); } /* validate twitch */ if (!is_empty($args['twitch']) && !valid_url($args['twitch'])) { throw new Exception(__("Please enter a valid Twitch Profile URL")); } /* validate linkedin */ if (!is_empty($args['linkedin']) && !valid_url($args['linkedin'])) { throw new Exception(__("Please enter a valid Linkedin Profile URL")); } /* validate vkontakte */ if (!is_empty($args['vkontakte']) && !valid_url($args['vkontakte'])) { throw new Exception(__("Please enter a valid Vkontakte Profile URL")); } /* update user */ $db->query(sprintf("UPDATE users SET user_social_facebook = %s, user_social_twitter = %s, user_social_youtube = %s, user_social_instagram = %s, user_social_twitch = %s, user_social_linkedin = %s, user_social_vkontakte = %s WHERE user_id = %s", secure($args['facebook']), secure($args['twitter']), secure($args['youtube']), secure($args['instagram']), secure($args['twitch']), secure($args['linkedin']), secure($args['vkontakte']), secure($this->_data['user_id'], 'int'))); break; case 'design': /* check if profile background enabled */ if (!$system['system_profile_background_enabled']) { throw new Exception(__("The profile background feature has been disabled by the admin")); } /* update user */ $db->query(sprintf("UPDATE users SET user_profile_background = %s WHERE user_id = %s", secure($args['user_profile_background']), secure($this->_data['user_id'], 'int'))); break; case 'password': /* validate all fields */ if (is_empty($args['current']) || is_empty($args['new']) || is_empty($args['confirm'])) { throw new Exception(__("You must fill in all of the fields")); } /* validate current password (MD5 check for versions < v2.5) */ if (md5($args['current']) != $this->_data['user_password'] && !password_verify($args['current'], $this->_data['user_password'])) { throw new Exception(__("Your current password is incorrect")); } /* validate new password */ if ($args['new'] != $args['confirm']) { throw new Exception(__("Your passwords do not match")); } if (strlen($args['new']) < 6) { throw new Exception(__("Your password must be at least 6 characters long. Please try another")); } if (strlen($args['new']) > 64) { throw new Exception(__("Your password must be less than 64 characters long. Please try another")); } /* update user */ $db->query(sprintf("UPDATE users SET user_password = %s WHERE user_id = %s", secure(_password_hash($args['new'])), secure($this->_data['user_id'], 'int'))); /* delete sessions */ $db->query(sprintf("DELETE FROM users_sessions WHERE session_id != %s AND user_id = %s", secure($this->_data['active_session_id']), secure($this->_data['user_id'], 'int'))); break; case 'two-factor': if ($system['two_factor_type'] != $args['type']) { _error(400); } /* prepare */ $args['two_factor_enabled'] = (isset($args['two_factor_enabled'])) ? '1' : '0'; switch ($system['two_factor_type']) { case 'email': if ($args['two_factor_enabled'] && !$this->_data['user_email_verified']) { throw new Exception(__("Two-Factor Authentication can't be enabled till you verify your email address")); } break; case 'sms': if ($args['two_factor_enabled'] && !$this->_data['user_phone']) { throw new Exception(__("Two-Factor Authentication can't be enabled till you enter your phone number")); } if ($args['two_factor_enabled'] && !$this->_data['user_phone_verified']) { throw new Exception(__("Two-Factor Authentication can't be enabled till you verify your phone number")); } break; case 'google': if (isset($args['gcode'])) { /* Google Authenticator */ $ga = new Sonata\GoogleAuthenticator\GoogleAuthenticator(); /* verify code */ if (!$ga->checkCode($this->_data['user_two_factor_gsecret'], $args['gcode'])) { throw new Exception(__("Invalid code, Try again or try to scan your QR code again")); } $args['two_factor_enabled'] = '1'; } break; } /* update user */ $db->query(sprintf("UPDATE users SET user_two_factor_enabled = %s, user_two_factor_type = %s WHERE user_id = %s", secure($args['two_factor_enabled']), secure($system['two_factor_type']), secure($this->_data['user_id'], 'int'))); break; case 'privacy': /* prepare */ $privacy = ['me', 'friends', 'public']; /* check if chat enabled */ $args['user_chat_enabled'] = (isset($args['user_chat_enabled'])) ? '1' : '0'; /* check if newsletter enabled */ $args['user_newsletter_enabled'] = (isset($args['user_newsletter_enabled'])) ? '1' : '0'; /* check if tips enabled */ $args['user_tips_enabled'] = (isset($args['user_tips_enabled'])) ? '1' : '0'; /* check if chat enabled */ $args['user_privacy_chat'] = (isset($args['user_privacy_chat'])) ? $args['user_privacy_chat'] : 'public'; /* check if pokes enabled */ $args['user_privacy_poke'] = (isset($args['user_privacy_poke'])) ? $args['user_privacy_poke'] : 'public'; /* check if gifts enabled */ $args['user_privacy_gifts'] = (isset($args['user_privacy_gifts'])) ? $args['user_privacy_gifts'] : 'public'; /* check if wall posts enabled */ $args['user_privacy_wall'] = (isset($args['user_privacy_wall'])) ? $args['user_privacy_wall'] : 'public'; /* check if genders enabled */ $args['user_privacy_gender'] = (isset($args['user_privacy_gender'])) ? $args['user_privacy_gender'] : 'public'; /* check if relationship info enabled */ $args['user_privacy_relationship'] = (isset($args['user_privacy_relationship'])) ? $args['user_privacy_relationship'] : 'public'; /* check if work info enabled */ $args['user_privacy_work'] = (isset($args['user_privacy_work'])) ? $args['user_privacy_work'] : 'public'; /* check if location info enabled */ $args['user_privacy_location'] = (isset($args['user_privacy_location'])) ? $args['user_privacy_location'] : 'public'; /* check if education info enabled */ $args['user_privacy_education'] = (isset($args['user_privacy_education'])) ? $args['user_privacy_education'] : 'public'; /* check if friends enabled */ $args['user_privacy_friends'] = (isset($args['user_privacy_friends'])) ? $args['user_privacy_friends'] : 'public'; /* check if subscriptions enabled */ $args['user_privacy_subscriptions'] = (isset($args['user_privacy_subscriptions'])) ? $args['user_privacy_subscriptions'] : 'public'; /* check if pages enabled */ $args['user_privacy_pages'] = (isset($args['user_privacy_pages'])) ? $args['user_privacy_pages'] : 'public'; /* check if groups enabled */ $args['user_privacy_groups'] = (isset($args['user_privacy_groups'])) ? $args['user_privacy_groups'] : 'public'; /* check if events enabled */ $args['user_privacy_events'] = (isset($args['user_privacy_events'])) ? $args['user_privacy_events'] : 'public'; /* check if valid privacy */ if (!in_array($args['user_privacy_chat'], $privacy) || !in_array($args['user_privacy_poke'], $privacy) || !in_array($args['user_privacy_gifts'], $privacy) || !in_array($args['user_privacy_wall'], $privacy) || !in_array($args['user_privacy_gender'], $privacy) || !in_array($args['user_privacy_relationship'], $privacy) || !in_array($args['user_privacy_birthdate'], $privacy) || !in_array($args['user_privacy_basic'], $privacy) || !in_array($args['user_privacy_work'], $privacy) || !in_array($args['user_privacy_location'], $privacy) || !in_array($args['user_privacy_education'], $privacy) || !in_array($args['user_privacy_other'], $privacy) || !in_array($args['user_privacy_friends'], $privacy) || !in_array($args['user_privacy_followers'], $privacy) || !in_array($args['user_privacy_subscriptions'], $privacy) || !in_array($args['user_privacy_photos'], $privacy) || !in_array($args['user_privacy_pages'], $privacy) || !in_array($args['user_privacy_groups'], $privacy) || !in_array($args['user_privacy_events'], $privacy)) { _error(400); } /* update user */ $db->query(sprintf( "UPDATE users SET user_chat_enabled = %s, user_newsletter_enabled = %s, user_tips_enabled = %s, user_privacy_chat = %s, user_privacy_poke = %s, user_privacy_gifts = %s, user_privacy_wall = %s, user_privacy_gender = %s, user_privacy_relationship = %s, user_privacy_birthdate = %s, user_privacy_basic = %s, user_privacy_work = %s, user_privacy_location = %s, user_privacy_education = %s, user_privacy_other = %s, user_privacy_friends = %s, user_privacy_followers = %s, user_privacy_subscriptions = %s, user_privacy_photos = %s, user_privacy_pages = %s, user_privacy_groups = %s, user_privacy_events = %s WHERE user_id = %s", secure($args['user_chat_enabled']), secure($args['user_newsletter_enabled']), secure($args['user_tips_enabled']), secure($args['user_privacy_chat']), secure($args['user_privacy_poke']), secure($args['user_privacy_gifts']), secure($args['user_privacy_wall']), secure($args['user_privacy_gender']), secure($args['user_privacy_relationship']), secure($args['user_privacy_birthdate']), secure($args['user_privacy_basic']), secure($args['user_privacy_work']), secure($args['user_privacy_location']), secure($args['user_privacy_education']), secure($args['user_privacy_other']), secure($args['user_privacy_friends']), secure($args['user_privacy_followers']), secure($args['user_privacy_subscriptions']), secure($args['user_privacy_photos']), secure($args['user_privacy_pages']), secure($args['user_privacy_groups']), secure($args['user_privacy_events']), secure($this->_data['user_id'], 'int') )); break; case 'notifications': /* prepare */ $args['chat_sound'] = (isset($args['chat_sound'])) ? '1' : '0'; $args['notifications_sound'] = (isset($args['notifications_sound'])) ? '1' : '0'; $args['email_post_likes'] = (isset($args['email_post_likes'])) ? '1' : '0'; $args['email_post_comments'] = (isset($args['email_post_comments'])) ? '1' : '0'; $args['email_post_shares'] = (isset($args['email_post_shares'])) ? '1' : '0'; $args['email_wall_posts'] = (isset($args['email_wall_posts'])) ? '1' : '0'; $args['email_mentions'] = (isset($args['email_mentions'])) ? '1' : '0'; $args['email_profile_visits'] = (isset($args['email_profile_visits'])) ? '1' : '0'; $args['email_friend_requests'] = (isset($args['email_friend_requests'])) ? '1' : '0'; $args['email_user_verification'] = (isset($args['email_user_verification'])) ? '1' : '0'; $args['email_user_post_approval'] = (isset($args['email_user_post_approval'])) ? '1' : '0'; $args['email_admin_verifications'] = (isset($args['email_admin_verifications'])) ? '1' : '0'; $args['email_admin_post_approval'] = (isset($args['email_admin_post_approval'])) ? '1' : '0'; $args['email_admin_user_approval'] = (isset($args['email_admin_user_approval'])) ? '1' : '0'; /* update user */ $db->query(sprintf("UPDATE users SET chat_sound = %s, notifications_sound = %s, email_post_likes = %s, email_post_comments = %s, email_post_shares = %s, email_wall_posts = %s, email_mentions = %s, email_profile_visits = %s, email_friend_requests = %s, email_user_verification = %s, email_user_post_approval = %s, email_admin_verifications = %s, email_admin_post_approval = %s, email_admin_user_approval = %s WHERE user_id = %s", secure($args['chat_sound']), secure($args['notifications_sound']), secure($args['email_post_likes']), secure($args['email_post_comments']), secure($args['email_post_shares']), secure($args['email_wall_posts']), secure($args['email_mentions']), secure($args['email_profile_visits']), secure($args['email_friend_requests']), secure($args['email_user_verification']), secure($args['email_user_post_approval']), secure($args['email_admin_verifications']), secure($args['email_admin_post_approval']), secure($args['email_admin_user_approval']), secure($this->_data['user_id'], 'int'))); break; case 'notifications_sound': /* prepare */ $args['notifications_sound'] = ($args['notifications_sound'] == 0) ? 0 : 1; /* update user */ $db->query(sprintf("UPDATE users SET notifications_sound = %s WHERE user_id = %s", secure($args['notifications_sound']), secure($this->_data['user_id'], 'int'))); break; case 'chat': /* prepare */ $args['user_chat_enabled'] = ($args['user_chat_enabled'] == 0) ? 0 : 1; /* update user */ $db->query(sprintf("UPDATE users SET user_chat_enabled = %s WHERE user_id = %s", secure($args['user_chat_enabled']), secure($this->_data['user_id'], 'int'))); break; case 'membership': /* videos */ $videos_query = ""; if ($this->_data['allowed_videos_categories'] > 0) { $package_videos_categories = json_decode(html_entity_decode($args['package_videos_categories']), true); if (!$package_videos_categories || count($package_videos_categories) < $this->_data['allowed_videos_categories']) { throw new Exception(__("You must select at least") . " " . $this->_data['allowed_videos_categories'] . " " . __("videos categories")); } if (count($package_videos_categories) > $this->_data['allowed_videos_categories']) { throw new Exception(__("You can't select more than") . " " . $this->_data['allowed_videos_categories'] . " " . __("videos categories")); } $videos_query = "user_package_videos_categories = " . secure($args['package_videos_categories']); } /* blogs */ $blogs_query = ""; if ($this->_data['allowed_blogs_categories'] > 0) { $package_blogs_categories = json_decode(html_entity_decode($args['package_blogs_categories']), true); if (!$package_blogs_categories || count($package_blogs_categories) < $this->_data['allowed_blogs_categories']) { throw new Exception(__("You must select at least") . " " . $this->_data['allowed_blogs_categories'] . " " . __("blogs categories")); } if (count($package_blogs_categories) > $this->_data['allowed_blogs_categories']) { throw new Exception(__("You can't select more than") . " " . $this->_data['allowed_blogs_categories'] . " " . __("blogs categories")); } $blogs_query = ($videos_query) ? ", " : ""; $blogs_query .= "user_package_blogs_categories = " . secure($args['package_blogs_categories']); } /* update user */ $db->query(sprintf("UPDATE users SET $videos_query $blogs_query WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); break; case 'monetization': /* check monetization permission */ if (!$this->_data['can_monetize_content']) { throw new Exception(__("The monetization system has been disabled by the admin")); } /* prepare */ $args['user_monetization_enabled'] = (isset($args['user_monetization_enabled'])) ? '1' : '0'; /* check if verification for monetization required */ if ($args['user_monetization_enabled'] && $system['verification_for_monetization'] && !$this->_data['user_verified']) { throw new Exception(__("To enable this feature your account must be verified")); } /* update user */ $db->query(sprintf("UPDATE users SET user_monetization_enabled = %s, user_monetization_chat_price = %s, user_monetization_call_price = %s WHERE user_id = %s", secure($args['user_monetization_enabled']), secure($args['user_monetization_chat_price'], 'float'), secure($args['user_monetization_call_price'], 'float'), secure($this->_data['user_id'], 'int'))); /* update monetization plans */ $this->update_monetization_plans(); break; } } /* ------------------------------- */ /* Verifications */ /* ------------------------------- */ /** * update_node_verification_status * * @param int $node_id * @param string $node_type * @param string $action * @return void */ public function update_node_verification_status($node_id, $node_type = 'user', $action = 'verify') { global $db; if (!in_array($node_type, ['user', 'page'])) { throw new Exception(__("Invalid node type")); } if (!in_array($action, ['verify', 'unverify'])) { throw new Exception(__("Invalid action")); } $status = ($action == 'verify') ? '1' : '0'; if ($node_type == 'page') { /* verify page */ $db->query(sprintf("UPDATE pages SET page_verified = %s WHERE page_id = %s", secure($status, 'int'), secure($node_id, 'int'))) or _error("SQL_ERROR_THROWEN"); } else { /* verify user */ $db->query(sprintf("UPDATE users SET user_verified = %s WHERE user_id = %s", secure($status, 'int'), secure($node_id, 'int'))) or _error("SQL_ERROR_THROWEN"); } /* remove all verification requests */ $db->query(sprintf("DELETE FROM verification_requests WHERE node_type = %s AND node_id = %s", secure($node_type), secure($node_id, 'int'))) or _error("SQL_ERROR_THROWEN"); } /** * send_verification_request * * @param int $node_id * @param string $node_type * @param array $inputs * @return void */ public function send_verification_request($node_id, $node_type, $inputs) { global $system, $db, $date; /* check if node has any pending requests */ $get_requests = $db->query(sprintf("SELECT COUNT(*) AS count FROM verification_requests WHERE node_id = %s AND node_type = %s AND `status` = '0'", secure($node_id, 'int'), secure($node_type))) or _error("SQL_ERROR_THROWEN"); if ($get_requests->fetch_assoc()['count'] > 0) { throw new ValidationException(__("You have a pending verification request")); } /* check if the user is the page admin */ if ($node_type == 'page' && !$this->check_page_adminship($this->_data['user_id'], $node_id)) { throw new ValidationException(__("You are not authorized to verify this page")); } /* valid inputs */ if ($system['verification_docs_required']) { if (!isset($inputs['photo']) || is_empty($inputs['photo'])) { throw new ValidationException(($node_type == 'page') ? __("Please attach your company incorporation file") : __("Please attach your photo")); } if (!isset($inputs['passport']) || is_empty($inputs['passport'])) { throw new ValidationException(($node_type == 'page') ? __("Please attach your tax file") : __("Please attach your Passport or National ID")); } } else { $inputs['photo'] = ''; $inputs['passport'] = ''; } if (!isset($inputs['message']) || is_empty($inputs['message'])) { throw new ValidationException(($node_type == 'page') ? __("Please share why your page should be verified") : __("Please share why your account should be verified")); } /* insert verification request */ if ($node_type == 'user') { $db->query(sprintf("INSERT INTO verification_requests (node_id, node_type, photo, passport, message, time, status) VALUES (%s, 'user', %s, %s, %s, %s, '0')", secure($node_id, 'int'), secure($inputs['photo']), secure($inputs['passport']), secure($inputs['message']), secure($date))); } else { $db->query(sprintf("INSERT INTO verification_requests (node_id, node_type, photo, passport, business_website, business_address, message, time, status) VALUES (%s, 'page', %s, %s, %s, %s, %s, %s, '0')", secure($node_id, 'int'), secure($inputs['photo']), secure($inputs['passport']), secure($inputs['business_website']), secure($inputs['business_address']), secure($inputs['message']), secure($date))); } /* send notification to admins & moderators */ $this->notify_system_admins("verification_request", true); } /** * delete_all_verification_requests * * @param int $node_id * @param string $node_type * @return void */ public function delete_all_verification_requests($node_id, $node_type) { global $db; $db->query(sprintf("DELETE FROM verification_requests WHERE node_id = %s AND node_type = %s", secure($node_id, 'int'), secure($node_type))) or _error("SQL_ERROR_THROWEN"); } /* ------------------------------- */ /* Addresses */ /* ------------------------------- */ /** * get_addresses * * @param array $args * @return array */ public function get_addresses() { global $db; $addresses = []; $get_addresses = $db->query(sprintf("SELECT * FROM users_addresses WHERE user_id = %s", secure($this->_data['user_id'], 'int'))) or _error("SQL_ERROR_THROWEN"); if ($get_addresses->num_rows > 0) { while ($address = $get_addresses->fetch_assoc()) { $addresses[] = $address; } } return $addresses; } /** * get_address * * @param int $address_id * @return array */ public function get_address($address_id) { global $db, $system; $get_address = $db->query(sprintf("SELECT * FROM users_addresses WHERE address_id = %s AND user_id = %s", secure($address_id, 'int'), secure($this->_data['user_id'], 'int'))) or _error("SQL_ERROR_THROWEN"); if ($get_address->num_rows == 0) { throw new NoDataException(__("No data found")); } $address = $get_address->fetch_assoc(); return $address; } /** * insert_address * * @param string $title * @param string $country * @param string $city * @param string $zip_code * @param string $phone * @param string $address * @return void */ public function insert_address($title, $country, $city, $zip_code, $phone, $address) { global $db, $system; /* validate title */ if (is_empty($title)) { throw new ValidationException(__("You must enter the title")); } /* validate country */ if (is_empty($country)) { throw new ValidationException(__("You must enter the country")); } /* validate city */ if (is_empty($city)) { throw new ValidationException(__("You must enter the city")); } /* validate zip code */ if (is_empty($zip_code)) { throw new ValidationException(__("You must enter the zip code")); } /* validate phone */ if (is_empty($phone)) { throw new ValidationException(__("You must enter the phone")); } /* validate address */ if (is_empty($address)) { throw new ValidationException(__("You must enter the address")); } /* insert */ $db->query(sprintf("INSERT INTO users_addresses (user_id, address_title, address_country, address_city, address_zip_code, address_phone, address_details) VALUES (%s, %s, %s, %s, %s, %s, %s)", secure($this->_data['user_id'], 'int'), secure($title), secure($country), secure($city), secure($zip_code), secure($phone), secure($address))) or _error("SQL_ERROR_THROWEN"); } /** * update_address * * @param int $address_id * @param string $title * @param string $country * @param string $city * @param string $zip_code * @param string $phone * @param string $address * @return void */ public function update_address($address_id, $title, $country, $city, $zip_code, $phone, $address) { global $db; /* check if this address belongs to the user */ $check_address = $db->query(sprintf("SELECT COUNT(*) AS count FROM users_addresses WHERE address_id = %s AND user_id = %s", secure($address_id, 'int'), secure($this->_data['user_id'], 'int'))) or _error("SQL_ERROR_THROWEN"); if ($check_address->fetch_assoc()['count'] == 0) { throw new AuthorizationException(__("You are not authorized to do this action")); } /* validate title */ if (is_empty($title)) { throw new ValidationException(__("You must enter the title")); } /* validate country */ if (is_empty($country)) { throw new ValidationException(__("You must enter the country")); } /* validate city */ if (is_empty($city)) { throw new ValidationException(__("You must enter the city")); } /* validate zip code */ if (is_empty($zip_code)) { throw new ValidationException(__("You must enter the zip code")); } /* validate phone */ if (is_empty($phone)) { throw new ValidationException(__("You must enter the phone")); } /* validate address */ if (is_empty($address)) { throw new ValidationException(__("You must enter the address")); } /* update */ $db->query(sprintf("UPDATE users_addresses SET address_title = %s, address_country = %s, address_city = %s, address_zip_code = %s, address_phone = %s, address_details = %s WHERE address_id = %s AND user_id = %s", secure($title), secure($country), secure($city), secure($zip_code), secure($phone), secure($address), secure($address_id, 'int'), secure($this->_data['user_id'], 'int'))) or _error("SQL_ERROR_THROWEN"); } /** * delete_address * * @param int $address_id * @return void */ public function delete_address($address_id) { global $db; $db->query(sprintf("DELETE FROM users_addresses WHERE address_id = %s AND user_id = %s", secure($address_id, 'int'), secure($this->_data['user_id'], 'int'))) or _error("SQL_ERROR_THROWEN"); } /* ------------------------------- */ /* Download User Information */ /* ------------------------------- */ /** * download_user_information * * @return array */ public function download_user_information() { global $db, $system, $smarty; $user_data = []; /* information */ if ($_SESSION['download_information']) { $this->_data['user_gender'] = $this->get_gender($this->_data['user_gender']); $user_data['information'] = $this->_data; /* user sessions */ $sessions = []; $get_sessions = $db->query(sprintf("SELECT * FROM users_sessions WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); if ($get_sessions->num_rows > 0) { while ($session = $get_sessions->fetch_assoc()) { $sessions[] = $session; } } $user_data['information']['sessions'] = $sessions; } /* friends */ if ($_SESSION['download_friends']) { $user_data['friends'] = $this->get_friends($this->_data['user_id'], 0, true); } /* followings */ if ($_SESSION['download_followings']) { $user_data['followings'] = $this->get_followings($this->_data['user_id'], 0, true); } /* followers */ if ($_SESSION['download_followers']) { $user_data['followers'] = $this->get_followers($this->_data['user_id'], 0, true); } /* pages */ if ($_SESSION['download_pages']) { $user_data['pages'] = $this->get_pages(['managed' => true, 'user_id' => $this->_data['user_id']]); } /* groups */ if ($_SESSION['download_groups']) { $user_data['groups'] = $this->get_groups(['get_all' => true, 'user_id' => $this->_data['user_id']]); } /* events */ if ($_SESSION['download_events']) { $user_data['events'] = $this->get_events(['get_all' => true, 'user_id' => $this->_data['user_id']]); } /* posts */ if ($_SESSION['download_posts']) { $user_data['posts'] = $this->get_posts(['get_all' => true, 'get' => 'posts_profile', 'id' => $this->_data['user_id']]); } /* assign variables */ $smarty->assign('user_data', $user_data); /* return */ $html_file = $smarty->fetch("information.tpl"); header('Content-disposition: attachment; filename=' . $this->_data['user_name'] . ".html"); header('Content-type: text/html'); print($html_file); exit; } /* ------------------------------- */ /* User Sign (in|up|out) ✅ */ /* ------------------------------- */ /** * sign_up * * @param array $args * @param array $device_info * @return void */ public function sign_up($args = [], $device_info = []) { global $db, $system, $date; /* prepare */ $args['from_web'] = (isset($args['from_web'])) ? $args['from_web'] : true; /* check invitation code */ if ($system['invitation_enabled']) { if (!$this->check_invitation_code($args['invitation_code'])) { throw new ValidationException(__("The invitation code is invalid or expired")); } } /* check IP */ $this->_check_ip(); /* validate */ if ($system['show_usernames_enabled']) { $args['first_name'] = $args['username']; $args['last_name'] = $args['username']; } else { if (!valid_name($args['first_name'])) { throw new ValidationException(__("Your first name contains invalid characters")); } if (strlen($args['first_name']) < $system['name_min_length']) { throw new ValidationException(__("Your first name must be at least") . " " . $system['name_min_length'] . " " . __("characters long. Please try another")); } if (!valid_name($args['last_name'])) { throw new ValidationException(__("Your last name contains invalid characters")); } if (strlen($args['last_name']) < $system['name_min_length']) { throw new ValidationException(__("Your last name must be at least") . " " . $system['name_min_length'] . " " . __("characters long. Please try another")); } } if (!valid_username($args['username'])) { throw new ValidationException(__("Please enter a valid username (a-z0-9_.) with minimum 3 characters long")); } if ($this->reserved_username($args['username'])) { throw new ValidationException(__("You can't use") . " " . $args['username'] . " " . __("as username")); } if ($this->check_username($args['username'])) { throw new ValidationException(__("Sorry, it looks like") . " " . $args['username'] . " " . __("belongs to an existing account")); } if (!valid_email($args['email'])) { throw new ValidationException(__("Please enter a valid email address")); } if ($this->check_email($args['email'])) { throw new ValidationException(__("Sorry, it looks like") . " " . $args['email'] . " " . __("belongs to an existing account")); } if ($system['activation_enabled'] && $system['activation_type'] == "sms") { if (is_empty($args['phone'])) { throw new ValidationException(__("Please enter a valid phone number")); } if ($this->check_phone($args['phone'])) { throw new ValidationException(__("Sorry, it looks like") . " " . $args['phone'] . " " . __("belongs to an existing account")); } } else { $args['phone'] = 'null'; } if (strlen($args['password']) < 6) { throw new ValidationException(__("Your password must be at least 6 characters long. Please try another")); } if (strlen($args['password']) > 64) { throw new ValidationException(__("Your password must be less than 64 characters long. Please try another")); } $args['gender'] = ($system['genders_disabled']) ? 1 : $args['gender']; if (!$system['genders_disabled'] && !$this->check_gender($args['gender'])) { throw new ValidationException(__("Please select a valid gender")); } /* check age restriction */ if ($system['age_restriction']) { if (!in_array($args['birth_month'], range(1, 12))) { throw new ValidationException(__("Please select a valid birth month (1-12)")); } if (!in_array($args['birth_day'], range(1, 31))) { throw new ValidationException(__("Please select a valid birth day (1-31)")); } if (!in_array($args['birth_year'], range(1905, 2017))) { throw new ValidationException(__("Please select a valid birth year (1905-2017)")); } if (date("Y") - $args['birth_year'] < $system['minimum_age']) { throw new ValidationException(__("Sorry, You must be") . " " . $system['minimum_age'] . " " . __("years old to register")); } $args['birth_date'] = $args['birth_year'] . '-' . $args['birth_month'] . '-' . $args['birth_day']; } else { $args['birth_date'] = 'null'; } /* set custom fields */ $custom_fields = $this->set_custom_fields($args); /* check if user applied as agency */ $user_group = (isset($args['apply_agency']) && $args['apply_agency'] == "on") ? 4 : 3; /* check reCAPTCHA */ if ($system['reCAPTCHA_enabled'] && $args['from_web']) { $recaptcha = new \ReCaptcha\ReCaptcha($system['reCAPTCHA_secret_key'], new \ReCaptcha\RequestMethod\CurlPost()); $resp = $recaptcha->verify($args['g-recaptcha-response'], get_user_ip()); if (!$resp->isSuccess()) { throw new ValidationException(__("The security check is incorrect. Please try again")); } } /* check newsletter agreement */ $newsletter_agree = (isset($args['newsletter_agree'])) ? '1' : '0'; /* check privacy agreement */ if (!isset($args['privacy_agree']) && $args['from_web']) { throw new ValidationException(__("You must read and agree to our terms and privacy policy")); } /* generate verification code */ $email_verification_code = ($system['activation_enabled'] && $system['activation_type'] == "email") ? get_hash_key(6, true) : 'null'; $phone_verification_code = ($system['activation_enabled'] && $system['activation_type'] == "sms") ? get_hash_key(6, true) : 'null'; /* set custom user group */ if ($system['select_user_group_enabled']) { $custom_user_group = ($args['custom_user_group'] != '0' && $this->check_user_group($args['custom_user_group'])) ? $args['custom_user_group'] : '0'; } else { $custom_user_group = ($system['default_custom_user_group'] != '0' && $this->check_user_group($system['default_custom_user_group'])) ? $system['default_custom_user_group'] : '0'; } /* check user approved and apply agency*/ if (!empty($args['apply_agency']) && $args['apply_agency'] === "on") { $user_approved = '0'; } else{ $user_approved = ($system['users_approval_enabled']) ? '0' : '1'; } /* register user */ $db->query(sprintf("INSERT INTO users (user_group, user_group_custom, user_name, user_email, user_phone, user_password,user_firstname, user_lastname, user_gender, user_birthdate,user_registered, user_email_verification_code, user_phone_verification_code,user_newsletter_enabled, user_approved) VALUES (%s, %s, %s, %s, %s, %s,%s, %s, %s, %s,%s, %s, %s,%s, %s)",secure($user_group),secure($custom_user_group),secure($args['username']),secure($args['email']),secure($args['phone']),secure(_password_hash($args['password'])),secure(ucwords($args['first_name'])),secure(ucwords($args['last_name'])),secure($args['gender']),secure($args['birth_date']),secure($date),secure($email_verification_code),secure($phone_verification_code),secure($newsletter_agree),secure($user_approved))); /* get user_id */ $user_id = $db->insert_id; /* set default privacy */ $this->_set_default_privacy($user_id); /* insert custom fields values */ if ($custom_fields) { foreach ($custom_fields as $field_id => $value) { $db->query(sprintf("INSERT INTO custom_fields_values (value, field_id, node_id, node_type) VALUES (%s, %s, %s, 'user')", secure($value), secure($field_id, 'int'), secure($user_id, 'int'))); } } /* send activation */ if ($system['activation_enabled']) { if ($system['activation_type'] == "email") { /* prepare activation email */ $subject = __("Just one more step to get started on") . " " . html_entity_decode(__($system['system_title']), ENT_QUOTES); $body = get_email_template("activation_email", $subject, ["first_name" => $args['first_name'], "last_name" => $args['last_name'], "email_verification_code" => $email_verification_code]); /* send email */ if (!_email($args['email'], $subject, $body['html'], $body['plain'])) { throw new Exception(__("Activation email could not be sent") . ", " . __("But you can login now")); } } else { /* prepare activation SMS */ $message = __($system['system_title']) . " " . __("Activation Code") . ": " . $phone_verification_code; /* send SMS */ if (!sms_send($args['phone'], $message)) { throw new Exception(__("Activation SMS could not be sent") . ", " . __("But you can login now")); } } } else { /* affiliates system (as activation disabled) */ $this->process_affiliates("registration", $user_id); } /* update invitation code */ if ($system['invitation_enabled']) { $this->update_invitation_code($args['invitation_code'], $user_id); } /* auto connect */ $this->auto_friend($user_id); $this->auto_follow($user_id); $this->auto_like($user_id); $this->auto_join($user_id); /* user approval system */ if ($system['users_approval_enabled']) { /* send notification to admins */ $this->notify_system_admins("pending_user", true, $user_id); } /* set authentication */ if ($args['from_web']) { $this->_set_authentication_cookies($user_id); } else { /* create JWT */ $jwt = $this->_set_authentication_JWT($user_id, $device_info); /* create new user object */ $user = new User($jwt); return ['token' => $jwt, 'user' => $user->_data]; } } /** * sign_in * * @param string $username_email * @param string $password * @param boolean $remember * @param boolean $from_web * @param array $device_info * @param boolean $connecting_account * * @return void */ public function sign_in($username_email, $password, $remember = false, $from_web = false, $device_info = [], $connecting_account = false) { global $db, $system, $date; /* valid inputs */ $username_email = trim($username_email); if (is_empty($username_email) || is_empty($password)) { throw new ValidationException(__("You must fill in all of the fields")); } /* check if username or email */ if (valid_email($username_email)) { $user = $this->check_email($username_email, true); if ($user === false) { throw new ValidationException(__("The email you entered does not belong to any account")); } $field = "user_email"; } else { if (!valid_username($username_email)) { throw new ValidationException(__("Please enter a valid email address or username")); } $user = $this->check_username($username_email, 'user', true); if ($user === false) { throw new ValidationException(__("The username you entered does not belong to any account")); } $field = "user_name"; } /* check brute-force attack detection */ if ($system['brute_force_detection_enabled']) { $lockout_time = $system['brute_force_lockout_time'] * 60; /* convert to seconds */ if (($user['user_failed_login_ip'] == get_user_ip()) && ($user['user_failed_login_count'] >= $system['brute_force_bad_login_limit']) && (time() - strtotime($user['user_first_failed_login']) < $lockout_time)) { throw new ValidationException(__("Your account is currently locked out. Please try again later!")); } } /* check password */ if (!password_verify($password, $user['user_password'])) { /* check brute-force attack detection */ if ($system['brute_force_detection_enabled']) { if ($user['user_first_failed_login'] && (time() - strtotime($user['user_first_failed_login']) > $lockout_time)) { /* reset the failed login count if the lockout time has passed */ $db->query(sprintf("UPDATE users SET user_first_failed_login = %s, user_failed_login_ip = %s, user_failed_login_count = 1 WHERE user_id = %s", secure($date), secure(get_user_ip()), secure($user['user_id'], 'int'))); } else { /* increment failed login count and update first failed login time & ip if necessary */ $db->query(sprintf("UPDATE users SET user_failed_login_count = user_failed_login_count + 1 WHERE user_id = %s", secure($user['user_id'], 'int'))); if (!$user['user_first_failed_login']) { $db->query(sprintf("UPDATE users SET user_first_failed_login = %s, user_failed_login_ip = %s WHERE user_id = %s", secure($date), secure(get_user_ip()), secure($user['user_id'], 'int'))); } } } throw new ValidationException(__("Please re-enter your password") . ", " . __("The password you entered is incorrect")); } /* two-factor authentication */ if ($user['user_two_factor_enabled']) { /* system two-factor disabled */ if (!$system['two_factor_enabled']) { $this->disable_two_factor_authentication($user['user_id']); goto set_authentication; } /* system two-factor method != user two-factor method */ if ($system['two_factor_type'] != $user['user_two_factor_type']) { $this->disable_two_factor_authentication($user['user_id']); goto set_authentication; } switch ($system['two_factor_type']) { case 'email': /* system two-factor method = email but user email not verified */ if (!$user['user_email_verified']) { $this->disable_two_factor_authentication($user['user_id']); goto set_authentication; } /* generate two-factor key */ $two_factor_key = get_hash_key(6, true); /* update user two factor key */ $db->query(sprintf("UPDATE users SET user_two_factor_key = %s WHERE user_id = %s", secure($two_factor_key), secure($user['user_id'], 'int'))); /* prepare method name */ $method = __("Email"); /* prepare activation email */ $subject = html_entity_decode(__($system['system_title']), ENT_QUOTES) . " " . __("Two-Factor Authentication Token"); $body = get_email_template("two_factor_email", $subject, ["user" => $user, "two_factor_key" => $two_factor_key]); /* send email */ if (!_email($user['user_email'], $subject, $body['html'], $body['plain'])) { throw new Exception(__("Two-factor authentication email could not be sent")); } break; case 'sms': /* system two-factor method = sms but not user phone not verified */ if (!$user['user_phone_verified']) { $this->disable_two_factor_authentication($user['user_id']); goto set_authentication; } /* generate two-factor key */ $two_factor_key = get_hash_key(6, true); /* update user two factor key */ $db->query(sprintf("UPDATE users SET user_two_factor_key = %s WHERE user_id = %s", secure($two_factor_key), secure($user['user_id'], 'int'))); /* prepare method name */ $method = __("Phone"); /* prepare activation SMS */ $message = __($system['system_title']) . " " . __("Two-factor authentication key") . ": " . $two_factor_key; /* send SMS */ if (!sms_send($user['user_phone'], $message)) { throw new Exception(__("Two-factor authentication SMS could not be sent")); } break; case 'google': /* prepare method name */ $method = __("Google Authenticator app"); break; } if ($from_web) { modal("#two-factor-authentication", "{user_id: '" . $user['user_id'] . "', remember: '" . $remember . "', method: '" . $method . "', connecting_account: '" . $connecting_account . "'}"); } else { return ['2FA' => true, 'user_id' => $user['user_id'], 'method' => $method, 'connecting_account' => $connecting_account]; } } /* set authentication */ set_authentication: if ($connecting_account) { return $user; } if ($from_web) { $this->_set_authentication_cookies($user['user_id'], $remember); } else { /* create JWT */ $jwt = $this->_set_authentication_JWT($user['user_id'], $device_info); /* create new user object */ $user = new User($jwt); return ['token' => $jwt, 'user' => $user->_data]; } } /** * sign_out * * @param boolean $from_web * @return void */ public function sign_out($from_web = false) { global $db, $date; /* delete the session */ $db->query(sprintf("DELETE FROM users_sessions WHERE session_token = %s AND user_id = %s", secure($this->_data['session_token']), secure($this->_data['user_id'], 'int'))); /* destroy the session */ session_destroy(); if ($from_web) { /* unset the cookies */ unset($_COOKIE[$this->_cookie_user_id]); unset($_COOKIE[$this->_cookie_user_token]); unset_cookie($this->_cookie_user_id); unset_cookie($this->_cookie_user_token); } } /** * _set_authentication_cookies * * @param integer $user_id * @param boolean $remember * @return void */ private function _set_authentication_cookies($user_id, $remember = false) { global $db, $system, $date; /* generate new token */ $session_token = get_hash_token(); /* check brute-force attack detection */ if ($system['brute_force_detection_enabled']) { $db->query(sprintf("UPDATE users SET user_failed_login_count = 0 WHERE user_id = %s", secure($user_id, 'int'))); } /* insert user session */ $db->query(sprintf("INSERT INTO users_sessions (session_token, session_date, user_id, user_ip, user_browser, user_os) VALUES (%s, %s, %s, %s, %s, %s)", secure($session_token), secure($date), secure($user_id, 'int'), secure(get_user_ip()), secure(get_user_browser()), secure(get_user_os()))); /* secured cookies */ $secured = (get_system_protocol() == "https") ? true : false; /* set authentication cookies */ $is_expired = ($remember) ? false : true; set_cookie($this->_cookie_user_id, $user_id, $is_expired); set_cookie($this->_cookie_user_token, $session_token, $is_expired); } /** * _set_authentication_JWT * * @param integer $user_id * @param array $device_info * @return string */ private function _set_authentication_JWT($user_id, $device_info) { global $db, $system, $date; /* generate new token */ $session_token = get_hash_token(); /* generate new JWT */ $payload = [ 'uid' => $user_id, 'token' => $session_token ]; $jwt = Firebase\JWT\JWT::encode($payload, JWT_SECRET, 'HS256'); /* check brute-force attack detection */ if ($system['brute_force_detection_enabled']) { $db->query(sprintf("UPDATE users SET user_failed_login_count = 0 WHERE user_id = %s", secure($user_id, 'int'))); } /* insert user session */ $db->query(sprintf("INSERT INTO users_sessions (session_token, session_date, session_type, user_id, user_ip, user_os, user_os_version, user_device_name) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)", secure($session_token), secure($date), secure($device_info['device_type']), secure($user_id, 'int'), secure(get_user_ip()), secure($device_info['device_os']), secure($device_info['device_os_version']), secure($device_info['device_name']))); return $jwt; } /** * _check_ip * * @return void */ private function _check_ip() { global $db, $system; if ($system['max_accounts'] > 0) { $check = $db->query(sprintf("SELECT user_ip, COUNT(*) FROM users_sessions WHERE user_ip = %s GROUP BY user_id", secure(get_user_ip()))); if ($check->num_rows >= $system['max_accounts']) { throw new ValidationException(__("You have reached the maximum number of account for your IP")); } } } private function _set_default_privacy($user_id) { global $system, $db; /* update user */ $db->query(sprintf( "UPDATE users SET user_privacy_chat = %s, user_privacy_poke = %s, user_privacy_gifts = %s, user_privacy_wall = %s, user_privacy_gender = %s, user_privacy_relationship = %s, user_privacy_birthdate = %s, user_privacy_basic = %s, user_privacy_work = %s, user_privacy_location = %s, user_privacy_education = %s, user_privacy_other = %s, user_privacy_friends = %s, user_privacy_followers = %s, user_privacy_subscriptions = %s, user_privacy_photos = %s, user_privacy_pages = %s, user_privacy_groups = %s, user_privacy_events = %s WHERE user_id = %s", secure($system['user_privacy_chat']), secure($system['user_privacy_poke']), secure($system['user_privacy_gifts']), secure($system['user_privacy_wall']), secure($system['user_privacy_gender']), secure($system['user_privacy_relationship']), secure($system['user_privacy_birthdate']), secure($system['user_privacy_basic']), secure($system['user_privacy_work']), secure($system['user_privacy_location']), secure($system['user_privacy_education']), secure($system['user_privacy_other']), secure($system['user_privacy_friends']), secure($system['user_privacy_followers']), secure($system['user_privacy_subscriptions']), secure($system['user_privacy_photos']), secure($system['user_privacy_pages']), secure($system['user_privacy_groups']), secure($system['user_privacy_events']), secure($user_id, 'int') )); } /* ------------------------------- */ /* Login As */ /* ------------------------------- */ /** * login_as * * @param integer $user_id * @return void */ public function login_as($user_id) { global $db, $system; /* check if the viewer is admin */ if (!$this->_is_admin) { throw new AuthorizationException(__("You are not authorized to do this action")); } /* check if the viewer is not the target user */ if ($user_id == $this->_data['user_id']) { throw new Exception(__("Sorry, it looks like this account belongs to you")); } /* check if the target user exists */ $user = $this->get_user($user_id); if (!$user) { throw new NoDataException(__("No data found")); } /* check if the target user is not the super admin */ if ($user['user_id'] == 1) { throw new AuthorizationException(__("You are not authorized to do this action")); } /* set login as cookie */ set_cookie($this->_cookie_user_login_as, $user['user_id']); } /** * revoke_login_as * * @return void */ public function revoke_login_as() { unset_cookie($this->_cookie_user_login_as); } /* ------------------------------- */ /* Connected Accounts ✅ */ /* ------------------------------- */ /** * get_connected_accounts * * @param integer $user_id * @return array */ public function get_connected_accounts($user_id = null) { global $db; $user_id = (isset($user_id)) ? $user_id : $this->_data['user_id']; $accounts = []; $get_accounts = $db->query(sprintf(' SELECT users.user_id, users.user_name, users.user_firstname, users.user_lastname, users.user_gender, users.user_picture, users.user_subscribed, users.user_verified FROM users WHERE user_id = %1$s UNION SELECT users.user_id, users.user_name, users.user_firstname, users.user_lastname, users.user_gender, users.user_picture, users.user_subscribed, users.user_verified FROM users INNER JOIN users_accounts ON users.user_id = users_accounts.account_id WHERE users_accounts.user_id = %1$s', secure($user_id, 'int'))); if ($get_accounts->num_rows > 0) { while ($account = $get_accounts->fetch_assoc()) { $account['user_picture'] = get_picture($account['user_picture'], $account['user_gender']); $accounts[] = $account; } } return $accounts; } /** * connected_account_signin * * @param string $username_email * @param string $password * @return void */ public function connected_account_signin($username_email, $password) { global $db; $user = $this->sign_in($username_email, $password, false, true, [], true); $this->connected_account_connect($user); } /** * connected_account_connect * * @param array $user * @return void */ public function connected_account_connect($user) { global $db; /* check if this user is the current user */ if ($user['user_id'] == $this->_data['user_id']) { throw new Exception(__("Sorry, it looks like this account belongs to you")); } /* check if this user is already connected to other master */ if ($user['user_master_account'] != $user['user_id']) { throw new Exception(__("Sorry, it looks like this account is already connected to another account")); } /* check if this user is a master account for other accounts */ $master_check = $db->query(sprintf("SELECT COUNT(*) AS count FROM users WHERE user_master_account = %s", secure($user['user_id'], 'int'))); if ($master_check->fetch_assoc()['count'] > 1) { throw new Exception(__("Sorry, it looks like this account is a master account for other accounts")); } /* insert new account as connected accounts */ $db->query(sprintf("INSERT INTO users_accounts (user_id, account_id) VALUES (%s, %s)", secure($this->_data['user_id'], 'int'), secure($user['user_id'], 'int'))); /* update new account master */ $db->query(sprintf("UPDATE users SET user_master_account = %s WHERE user_id = %s", secure($this->_data['user_id'], 'int'), secure($user['user_id'], 'int'))); } /** * connected_account_switch * * @param integer $account_id * @return void */ public function connected_account_switch($account_id) { global $db; /* search connected account if this account belongs to current user */ if (array_search($account_id, array_column($this->_data['connected_accounts'], 'user_id')) === false) { throw new Exception(__("Sorry, it looks like this account doesn't belong to you")); } $this->_set_authentication_cookies($account_id, true); } /** * connected_account_remove * * @param integer $account_id * @return void */ public function connected_account_remove($account_id) { global $db; /* search connected account if this account belongs to current user */ if (array_search($account_id, array_column($this->_data['connected_accounts'], 'user_id')) === false) { throw new Exception(__("Sorry, it looks like this account doesn't belong to you")); } /* remove from connected accounts */ $db->query(sprintf("DELETE FROM users_accounts WHERE user_id = %s AND account_id = %s", secure($this->_data['user_id'], 'int'), secure($account_id, 'int'))); /* update target user master */ $db->query(sprintf("UPDATE users SET user_master_account = user_id WHERE user_id = %s", secure($account_id, 'int'))); } /** * connected_account_revoke * * @return void */ public function connected_account_revoke() { global $db; /* remove from connected accounts */ $db->query(sprintf("DELETE FROM users_accounts WHERE user_id = %s AND account_id = %s", secure($this->_data['user_master_account'], 'int'), secure($this->_data['user_id'], 'int'))); /* update current user master */ $db->query(sprintf("UPDATE users SET user_master_account = user_id WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); } /* ------------------------------- */ /* Getting Started ✅ */ /* ------------------------------- */ /** * getting_satrted_update * * @param array $args * @return void */ public function getting_satrted_update($args) { global $db; /* validate country */ if ($args['country'] == "none") { throw new ValidationException(__("You must select valid country")); } else { if (!$this->check_country($args['country'])) { throw new ValidationException(__("You must select valid country")); } } /* validate work website */ if (!is_empty($args['work_url'])) { /* check if contains https:// or http:// if not add it */ if (!preg_match("~^(?:f|ht)tps?://~i", $args['work_url'])) { $args['work_url'] = "https://" . $args['work_url']; } if (!valid_url($args['work_url'])) { throw new ValidationException(__("Please enter a valid work website")); } } else { $args['work_url'] = 'null'; } /* update user */ $db->query(sprintf("UPDATE users SET user_country = %s, user_work_title = %s, user_work_place = %s, user_work_url = %s, user_current_city = %s, user_hometown = %s, user_edu_major = %s, user_edu_school = %s, user_edu_class = %s WHERE user_id = %s", secure($args['country'], 'int'), secure($args['work_title']), secure($args['work_place']), secure($args['work_url']), secure($args['city']), secure($args['hometown']), secure($args['edu_major']), secure($args['edu_school']), secure($args['edu_class']), secure($this->_data['user_id'], 'int'))); } /** * getting_satrted_finish * * @return void */ public function getting_satrted_finish() { global $db, $system; // check if there is any required data if ($system['getting_started_profile_image_required'] || $system['getting_started_location_required'] || $system['getting_started_education_required'] || $system['getting_started_work_required']) { $user_info = $this->get_user($this->_data['user_id']); /* check if profile image required */ if ($system['getting_started_profile_image_required'] && is_empty($user_info['user_picture'])) { throw new Exception(__("You must upload your profile image")); } /* check if location data required */ if ($system['getting_started_location_required'] && (is_empty($user_info['user_country']) || is_empty($user_info['user_current_city']) || is_empty($user_info['user_hometown']))) { throw new Exception(__("You must enter your location info")); } /* check if work data required */ if ($system['getting_started_work_required'] && (is_empty($user_info['user_work_title']) || is_empty($user_info['user_work_place']))) { throw new Exception(__("You must enter your work info")); } /* check if education data required */ if ($system['getting_started_education_required'] && (is_empty($user_info['user_edu_major']) || is_empty($user_info['user_edu_school']) || is_empty($user_info['user_edu_class']))) { throw new Exception(__("You must enter your education info")); } } // update user info $db->query(sprintf("UPDATE users SET user_started = '1' WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); // auto connect (custom country) $this->auto_friend($this->_data['user_id'], $this->_data['user_country']); $this->auto_follow($this->_data['user_id'], $this->_data['user_country']); $this->auto_like($this->_data['user_id'], $this->_data['user_country']); $this->auto_join($this->_data['user_id'], $this->_data['user_country']); } /* ------------------------------- */ /* Social Login */ /* ------------------------------- */ /** * social_login * * @param string $provider * @param object $user_profile * * @return void */ public function social_signin($provider, $user_profile) { global $db, $system, $smarty; switch ($provider) { case 'facebook': $social_id = "facebook_id"; $social_connected = "facebook_connected"; break; case 'google': $social_id = "google_id"; $social_connected = "google_connected"; break; case 'twitter': $social_id = "twitter_id"; $social_connected = "twitter_connected"; break; case 'instagram': $social_id = "instagram_id"; $social_connected = "instagram_connected"; break; case 'linkedin': case 'LinkedInOpenID': $social_id = "linkedin_id"; $social_connected = "linkedin_connected"; break; case 'vkontakte': $social_id = "vkontakte_id"; $social_connected = "vkontakte_connected"; break; case 'wordpress': $social_id = "wordpress_id"; $social_connected = "wordpress_connected"; break; case 'sngine': $social_id = "sngine_id"; $social_connected = "sngine_connected"; break; } /* check if user connected or not */ $check_user = $db->query(sprintf("SELECT user_id FROM users WHERE $social_id = %s", secure($user_profile->identifier))); if ($check_user->num_rows > 0) { /* social account connected and just signing-in */ $user = $check_user->fetch_assoc(); /* signout if user logged-in */ if ($this->_logged_in) { $this->sign_out(true); } /* set authentication cookies */ $this->_set_authentication_cookies($user['user_id'], true); redirect(); } else { /* user cloud be connecting his social account or signing-up */ if ($this->_logged_in) { /* [1] connecting social account */ $db->query(sprintf("UPDATE users SET $social_connected = '1', $social_id = %s WHERE user_id = %s", secure($user_profile->identifier), secure($this->_data['user_id'], 'int'))); redirect('/settings/linked'); } else { /* [2] signup with social account */ $_SESSION['social_id'] = $user_profile->identifier; page_header(__($system['system_title']) . " › " . __("Sign Up")); $smarty->assign('provider', $provider); $smarty->assign('user_profile', $user_profile); $smarty->assign('genders', $this->get_genders()); if ($system['select_user_group_enabled']) { $smarty->assign('user_groups', $this->get_users_groups()); } $smarty->display("signup_social.tpl"); } } } /** * social_signup * * @param string $first_name * @param string $last_name * @param string $username * @param string $email * @param string $password * @param string $gender * @param integer $custom_user_group * @param boolean $newsletter_agree * @param boolean $privacy_agree * @param string $avatar * @param string $provider * @param string $invitation_code * @return void */ public function social_signup($first_name, $last_name, $username, $email, $password, $gender, $custom_user_group, $newsletter_agree, $privacy_agree, $avatar, $provider, $invitation_code = "") { global $db, $system, $date; switch ($provider) { case 'facebook': $social_id = "facebook_id"; $social_connected = "facebook_connected"; break; case 'google': $social_id = "google_id"; $social_connected = "google_connected"; break; case 'twitter': $social_id = "twitter_id"; $social_connected = "twitter_connected"; break; case 'instagram': $social_id = "instagram_id"; $social_connected = "instagram_connected"; break; case 'linkedin': case 'LinkedInOpenID': $social_id = "linkedin_id"; $social_connected = "linkedin_connected"; break; case 'vkontakte': $social_id = "vkontakte_id"; $social_connected = "vkontakte_connected"; break; case 'wordpress': $social_id = "wordpress_id"; $social_connected = "wordpress_connected"; break; case 'sngine': $social_id = "sngine_id"; $social_connected = "sngine_connected"; break; default: _error(400); break; } /* check invitation code */ if ($system['invitation_enabled']) { if (!$this->check_invitation_code($invitation_code)) { throw new Exception(__("The invitation code is invalid or expired")); } } /* check IP */ $this->_check_ip(); if (is_empty($first_name) || is_empty($last_name) || is_empty($username) || is_empty($email) || is_empty($password)) { throw new Exception(__("You must fill in all of the fields")); } if (!valid_username($username)) { throw new Exception(__("Please enter a valid username (a-z0-9_.) with minimum 3 characters long")); } if ($this->reserved_username($username)) { throw new Exception(__("You can't use") . " " . $username . " " . __("as username")); } if ($this->check_username($username)) { throw new Exception(__("Sorry, it looks like") . " " . $username . " " . __("belongs to an existing account")); } if (!valid_email($email)) { throw new Exception(__("Please enter a valid email address")); } if ($this->check_email($email)) { throw new Exception(__("Sorry, it looks like") . " " . $email . " " . __("belongs to an existing account")); } if (strlen($password) < 6) { throw new Exception(__("Your password must be at least 6 characters long. Please try another")); } if (strlen($password) > 64) { throw new Exception(__("Your password must be less than 64 characters long. Please try another")); } if (!valid_name($first_name)) { throw new Exception(__("Your first name contains invalid characters")); } if (strlen($first_name) < $system['name_min_length']) { throw new Exception(__("Your first name must be at least") . " " . $system['name_min_length'] . " " . __("characters long. Please try another")); } if (!valid_name($last_name)) { throw new Exception(__("Your last name contains invalid characters")); } if (strlen($last_name) < $system['name_min_length']) { throw new Exception(__("Your last name must be at least") . " " . $system['name_min_length'] . " " . __("characters long. Please try another")); } $gender = ($system['genders_disabled']) ? 1 : $gender; if (!$system['genders_disabled'] && !$this->check_gender($gender)) { throw new Exception(__("Please select a valid gender")); } /* check newsletter agreement */ $newsletter_agree = (isset($args['newsletter_agree'])) ? '1' : '0'; /* check privacy agreement */ if (!isset($privacy_agree)) { throw new Exception(__("You must read and agree to our terms and privacy policy")); } /* save avatar */ $image_name = save_picture_from_url($avatar); /* set custom user group */ if ($system['select_user_group_enabled']) { $custom_user_group = ($custom_user_group != '0' && $this->check_user_group($custom_user_group)) ? $custom_user_group : '0'; } else { $custom_user_group = ($system['default_custom_user_group'] != '0' && $this->check_user_group($system['default_custom_user_group'])) ? $system['default_custom_user_group'] : '0'; } /* check user approved */ $user_approved = ($system['users_approval_enabled']) ? '0' : '1'; /* register user */ $db->query(sprintf("INSERT INTO users (user_group_custom, user_name, user_email, user_password, user_firstname, user_lastname, user_gender, user_registered, user_activated, user_picture, $social_id, $social_connected, user_approved) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, '1', %s, %s, '1', %s)", secure($custom_user_group), secure($username), secure($email), secure(_password_hash($password)), secure(ucwords($first_name)), secure(ucwords($last_name)), secure($gender), secure($date), secure($image_name), secure($_SESSION['social_id']), secure($user_approved))); /* get user_id */ $user_id = $db->insert_id; /* set default privacy */ $this->_set_default_privacy($user_id); /* affiliates system */ $this->process_affiliates("registration", $user_id); /* update invitation code */ if ($system['invitation_enabled']) { $this->update_invitation_code($invitation_code, $user_id); } /* auto connect */ $this->auto_friend($user_id); $this->auto_follow($user_id); $this->auto_like($user_id); $this->auto_join($user_id); /* user approval system */ if ($system['users_approval_enabled']) { /* send notification to admins */ $this->notify_system_admins("pending_user", true, $user_id); } /* set authentication cookies */ $this->_set_authentication_cookies($user_id); } /* ------------------------------- */ /* Two-Factor Authentication ✅ */ /* ------------------------------- */ /** * two_factor_authentication * * @param string $two_factor_key * @param integer $user_id * @param boolean $remember * @param boolean $from_web * @param array $device_info * @param boolean $connecting_account * @return void */ public function two_factor_authentication($two_factor_key, $user_id, $remember = false, $from_web = false, $device_info = [], $connecting_account = false) { global $db, $system; if ($system['two_factor_type'] == "google") { /* get user */ $get_user = $db->query(sprintf("SELECT user_two_factor_gsecret FROM users WHERE user_id = %s", secure($user_id, 'int'))); if ($get_user->num_rows == 0) { _error(400); } $_user = $get_user->fetch_assoc(); /* Google Authenticator */ $ga = new Sonata\GoogleAuthenticator\GoogleAuthenticator(); /* verify code */ if (!$ga->checkCode($_user['user_two_factor_gsecret'], $two_factor_key)) { throw new ValidationException(__("Invalid code, please try again")); } } else { /* check two-factor key */ $check_key = $db->query(sprintf("SELECT COUNT(*) as count FROM users WHERE user_id = %s AND user_two_factor_key = %s", secure($user_id, 'int'), secure($two_factor_key))); if ($check_key->fetch_assoc()['count'] == 0) { throw new ValidationException(__("Invalid code, please try again")); } } /* set authentication */ if ($connecting_account) { $user = $this->get_user($user_id); $this->connected_account_connect($user); } if ($from_web) { $this->_set_authentication_cookies($user_id, $remember); } else { /* create JWT */ $jwt = $this->_set_authentication_JWT($user_id, $device_info); /* create new user object */ $user = new User($jwt); return ['token' => $jwt, 'user' => $user->_data]; } } /** * disable_two_factor_authentication * * @param integer $user_id * * @return void */ public function disable_two_factor_authentication($user_id) { global $db; $db->query(sprintf("UPDATE users SET user_two_factor_enabled = '0', user_two_factor_type = null, user_two_factor_key = null, user_two_factor_gsecret = null WHERE user_id = %s", secure($user_id, 'int'))); } /* ------------------------------- */ /* Password ✅ */ /* ------------------------------- */ /** * forget_password * * @param string $email * @param string $recaptcha_response * @param bool $from_web * @return void */ public function forget_password($email, $recaptcha_response = null, $from_web = false) { global $db, $system; if (!valid_email($email)) { throw new ValidationException(__("Please enter a valid email address")); } if (!$this->check_email($email)) { throw new ValidationException(__("Sorry, it looks like") . " " . $email . " " . __("doesn't belong to any account")); } /* check reCAPTCHA */ if ($system['reCAPTCHA_enabled'] && $from_web) { $recaptcha = new \ReCaptcha\ReCaptcha($system['reCAPTCHA_secret_key'], new \ReCaptcha\RequestMethod\CurlPost()); $resp = $recaptcha->verify($recaptcha_response, get_user_ip()); if (!$resp->isSuccess()) { throw new ValidationException(__("The security check is incorrect. Please try again")); } } /* generate reset key */ $reset_key = get_hash_key(6, true); /* update user */ $db->query(sprintf("UPDATE users SET user_reset_key = %s, user_reseted = '1' WHERE user_email = %s", secure($reset_key), secure($email))); /* send reset email */ /* prepare reset email */ $subject = __("Forget password activation key!"); $body = get_email_template("forget_password_email", $subject, ["email" => $email, "reset_key" => $reset_key]); /* send email */ if (!_email($email, $subject, $body['html'], $body['plain'])) { throw new Exception(__("Activation key email could not be sent!")); } } /** * forget_password_confirm * * @param string $email * @param string $reset_key * @return void */ public function forget_password_confirm($email, $reset_key) { global $db; if (!valid_email($email)) { throw new ValidationException(__("Invalid email, please try again")); } /* check reset key */ $check_key = $db->query(sprintf("SELECT COUNT(*) as count FROM users WHERE user_email = %s AND user_reset_key = %s AND user_reseted = '1'", secure($email), secure($reset_key))); if ($check_key->fetch_assoc()['count'] == 0) { throw new ValidationException(__("Invalid code, please try again")); } } /** * forget_password_reset * * @param string $email * @param string $reset_key * @param string $password * @param string $confirm * @return void */ public function forget_password_reset($email, $reset_key, $password, $confirm) { global $db; if (!valid_email($email)) { throw new ValidationException(__("Invalid email, please try again")); } /* check reset key */ $check_key = $db->query(sprintf("SELECT COUNT(*) as count FROM users WHERE user_email = %s AND user_reset_key = %s AND user_reseted = '1'", secure($email), secure($reset_key))); if ($check_key->fetch_assoc()['count'] == 0) { throw new ValidationException(__("Invalid code, please try again")); } /* check password length */ if (strlen($password) < 6) { throw new ValidationException(__("Your password must be at least 6 characters long. Please try another")); } if (strlen($password) > 64) { throw new ValidationException(__("Your password must be less than 64 characters long. Please try another")); } /* check password confirm */ if ($password !== $confirm) { throw new ValidationException(__("Your passwords do not match. Please try another")); } /* update user password */ $db->query(sprintf("UPDATE users SET user_password = %s, user_reseted = '0' WHERE user_email = %s", secure(_password_hash($password)), secure($email))); /* delete sessions */ $db->query(sprintf("DELETE FROM users_sessions WHERE user_id = (SELECT user_id FROM users WHERE user_email = %s)", secure($email))); } /* ------------------------------- */ /* Activation Email ✅ */ /* ------------------------------- */ /** * activation_email * * @param string $code * @return void */ public function activation_email($code) { global $db, $system; /* check user */ if ($this->_data['user_email_verified']) { return; } if ($this->_data['user_email_verification_code'] != $code) { throw new ValidationException(__("Invalid verification code")); } /* check if user [1] activate his account & verify his email or [2] just verify his email */ if ($system['activation_enabled'] && $system['activation_type'] == "email" && !$this->_data['user_activated']) { /* [1] activate his account & verify his email */ $db->query(sprintf("UPDATE users SET user_activated = '1', user_email_verified = '1' WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); /* affiliates system */ $this->process_affiliates("registration", $this->_data['user_id'], $this->_data['user_referrer_id']); } else { /* [2] just verify his email */ $db->query(sprintf("UPDATE users SET user_email_verified = '1' WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); } } /** * activation_email_resend * * @param integer $user_id * @return void */ public function activation_email_resend($user_id = null) { global $db, $system; if (isset($user_id)) { $user = $this->get_user($user_id); if (!$user) { throw new NoDataException(__("No data found")); } $to_email = $user['user_email']; $to_name = ($system['show_usernames_enabled']) ? $user['user_name'] : $user['user_firstname'] . " " . $user['user_lastname']; } else { $user_id = $this->_data['user_id']; $to_email = $this->_data['user_email']; $to_name = $this->_data['name']; } /* generate email verification code */ $email_verification_code = get_hash_key(6, true); /* update user */ $db->query(sprintf("UPDATE users SET user_email_verification_code = %s WHERE user_id = %s", secure($email_verification_code), secure($user_id, 'int'))); /* prepare activation email */ $subject = __("Just one more step to get started on") . " " . html_entity_decode(__($system['system_title']), ENT_QUOTES); $body = get_email_template("activation_email", $subject, ["name" => $to_name, "email_verification_code" => $email_verification_code]); /* send email */ if (!_email($to_email, $subject, $body['html'], $body['plain'])) { throw new Exception(__("Activation email could not be sent")); } } /** * activation_email_reset * * @param string $email * @return void */ public function activation_email_reset($email) { global $db, $system; if (!valid_email($email)) { throw new ValidationException(__("Please enter a valid email address")); } if ($this->check_email($email)) { throw new ValidationException(__("Sorry, it looks like") . " " . $email . " " . __("belongs to an existing account")); } /* generate email verification code */ $email_verification_code = get_hash_key(6, true); /* check if activation via email enabled */ if ($system['activation_enabled'] && $system['activation_type'] == "email") { /* update user (not activated) */ $db->query(sprintf("UPDATE users SET user_email = %s, user_email_verified = '0', user_email_verification_code = %s, user_activated = '0' WHERE user_id = %s", secure($email), secure($email_verification_code), secure($this->_data['user_id'], 'int'))); } else { /* update user */ $db->query(sprintf("UPDATE users SET user_email = %s, user_email_verified = '0', user_email_verification_code = %s WHERE user_id = %s", secure($email), secure($email_verification_code), secure($this->_data['user_id'], 'int'))); } /* prepare activation email */ $subject = __("Just one more step to get started on") . " " . html_entity_decode(__($system['system_title']), ENT_QUOTES); $body = get_email_template("activation_email", $subject, ["name" => $this->_data['name'], "email_verification_code" => $email_verification_code]); /* send email */ if (!_email($email, $subject, $body['html'], $body['plain'])) { throw new Exception(__("Activation email could not be sent")); } } /* ------------------------------- */ /* Activation Phone ✅ */ /* ------------------------------- */ /** * activation_phone * * @param string $code * @return void */ public function activation_phone($code) { global $db, $system; /* check if phone already verified */ if ($this->_data['user_phone_verified']) { return; } /* check the verification code */ if ($this->_data['user_phone_verification_code'] != $code) { throw new ValidationException(__("Invalid code, please try again")); } /* check if user [1] activate his account & his phone or [2] just verify his phone */ if ($system['activation_enabled'] && $system['activation_type'] == "sms" && !$this->_data['user_activated']) { /* [1] activate his account & his phone */ $db->query(sprintf("UPDATE users SET user_activated = '1', user_phone_verified = '1' WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); /* affiliates system */ $this->process_affiliates("registration", $this->_data['user_id'], $this->_data['user_referrer_id']); } else { /* [2] just verify his phone */ $db->query(sprintf("UPDATE users SET user_phone_verified = '1' WHERE user_id = %s", secure($this->_data['user_id'], 'int'))); } } /** * activation_phone_resend * * @return void */ public function activation_phone_resend() { global $db, $system; /* generate phone verification code */ $phone_verification_code = get_hash_key(6, true); /* update user */ $db->query(sprintf("UPDATE users SET user_phone_verification_code = %s WHERE user_id = %s", secure($phone_verification_code), secure($this->_data['user_id'], 'int'))); /* prepare activation SMS */ $message = __($system['system_title']) . " " . __("Activation Code") . ": " . $phone_verification_code; /* send SMS */ if (!sms_send($this->_data['user_phone'], $message)) { throw new Exception(__("Activation SMS could not be sent")); } } /** * activation_phone_reset * * @param string $phone * @return void */ public function activation_phone_reset($phone) { global $db, $system; if (is_empty($phone)) { throw new ValidationException(__("Please enter a valid phone number")); } if ($this->check_phone($phone)) { throw new ValidationException(__("Sorry, it looks like") . " " . $phone . " " . __("belongs to an existing account")); } /* generate phone verification code */ $phone_verification_code = get_hash_key(6, true); /* check if activation via sms enabled */ if ($system['activation_enabled'] && $system['activation_type'] == "sms") { /* update user (not activated) */ $db->query(sprintf("UPDATE users SET user_phone = %s, user_phone_verified = '0', user_phone_verification_code = %s, user_activated = '0' WHERE user_id = %s", secure($phone), secure($phone_verification_code), secure($this->_data['user_id'], 'int'))); } else { /* update user */ $db->query(sprintf("UPDATE users SET user_phone = %s, user_phone_verified = '0', user_phone_verification_code = %s WHERE user_id = %s", secure($phone), secure($phone_verification_code), secure($this->_data['user_id'], 'int'))); } /* prepare activation SMS */ $message = __($system['system_title']) . " " . __("Activation Code") . ": " . $phone_verification_code; /* send SMS */ if (!sms_send($phone, $message)) { throw new Exception(__("Activation SMS could not be sent")); } } /* ------------------------------- */ /* Security Checks ✅ */ /* ------------------------------- */ /** * check_password * * @param string $password * @return void * */ public function check_password($password) { /* check if empty */ if (is_empty($password)) { throw new ValidationException(__("You have to enter your password to continue")); } /* validate current password */ if (!password_verify($password, $this->_data['user_password'])) { throw new ValidationException(__("Your current password is incorrect")); } } /** * check_email * * @param string $email * @param boolean $return_info * @return boolean|array * */ public function check_email($email, $return_info = false) { global $db; /* check if banned by the system */ $email_domain = explode('@', $email)[1]; $check_banned = $db->query(sprintf("SELECT COUNT(*) as count FROM blacklist WHERE node_type = 'email' AND node_value = %s", secure(explode('@', $email)[1]))); if ($check_banned->fetch_assoc()['count'] > 0) { throw new ValidationException(__("Sorry but this provider") . " " . $email_domain . " " . __("is not allowed in our system")); } $query = $db->query(sprintf("SELECT * FROM users WHERE user_email = %s", secure($email))); if ($query->num_rows > 0) { if ($return_info) { $info = $query->fetch_assoc(); return $info; } return true; } return false; } /** * check_phone * * @param string $phone * @return boolean * */ public function check_phone($phone) { global $db; $query = $db->query(sprintf("SELECT COUNT(*) as count FROM users WHERE user_phone = %s", secure($phone))); if ($query->fetch_assoc()['count'] > 0) { return true; } return false; } /** * check_username * * @param string $username * @param string $type * @param boolean $return_info * @return boolean|array */ public function check_username($username, $type = 'user', $return_info = false) { global $db; /* check if banned by the system */ $check_banned = $db->query(sprintf("SELECT COUNT(*) as count FROM blacklist WHERE node_type = 'username' AND node_value = %s", secure($username))); if ($check_banned->fetch_assoc()['count'] > 0) { throw new ValidationException(__("Sorry but this username") . " " . $username . " " . __("is not allowed in our system")); } /* check type (user|page|group) */ switch ($type) { case 'page': $query = $db->query(sprintf("SELECT * FROM pages WHERE page_name = %s", secure($username))); break; case 'group': $query = $db->query(sprintf("SELECT * FROM `groups` WHERE group_name = %s", secure($username))); break; default: $query = $db->query(sprintf("SELECT * FROM users WHERE user_name = %s", secure($username))); break; } if ($query->num_rows > 0) { if ($return_info) { $info = $query->fetch_assoc(); return $info; } return true; } return false; } /** * reserved_username * * @param string $username * @return boolean */ public function reserved_username($username) { global $system; if (!$system['reserved_usernames_enabled']) { return false; } /* make a list from target usernames */ $reserved_usernames = array_column(json_decode(html_entity_decode($system['reserved_usernames']), true), "value"); if (count($reserved_usernames) == 0) { return false; } if (in_array(strtolower($username), $reserved_usernames)) { return true; } return false; } }
( ! ) Fatal error: Uncaught Error: Class "User" not found in /var/www/html/realcoreapp/bootstrap.php on line 98
( ! ) Error: Class "User" not found in /var/www/html/realcoreapp/bootstrap.php on line 98
Call Stack
#TimeMemoryFunctionLocation
10.0000484016{main}( ).../profile.php:0
20.0001484968require( '/var/www/html/realcoreapp/bootloader.php ).../profile.php:11
30.0001485992require( '/var/www/html/realcoreapp/bootstrap.php ).../bootloader.php:11