PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / 3.2.13
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar v3.2.13
3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 All 156 releases
notificationx / includes / Core / Rest / Posts.php

Posts.php in NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar 3.2.13, at includes/Core/Rest/Posts.php

344 lines 12.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace NotificationX\Core\Rest;
4
5 use FluentForm\Framework\Database\Query\Expression;
6 use NotificationX\Core\Database;
7 use NotificationX\Core\PostType;
8 use NotificationX\Core\REST;
9 use NotificationX\Extensions\ExtensionFactory;
10 use NotificationX\Extensions\GlobalFields;
11 use NotificationX\GetInstance;
12 use NotificationX\NotificationX;
13 use WP_REST_Controller;
14 use WP_REST_Response;
15 use WP_REST_Server;
16 use WP_Error;
17
18 /**
19 * @method static Posts get_instance($args = null)
20 */
21 class Posts extends WP_REST_Controller {
22 /**
23 * Instance of NotificationX
24 *
25 * @var NotificationX
26 */
27 use GetInstance;
28
29 /**
30 * Post type.
31 *
32 * @since 4.7.0
33 * @var string
34 */
35 protected $post_type;
36
37 /**
38 * Constructor.
39 *
40 * @since 4.7.0
41 *
42 * @param string $post_type Post type.
43 */
44 public function __construct() {
45 $this->namespace = 'notificationx/v1';
46 $this->rest_base = 'nx';
47 add_action('rest_api_init', [$this, 'register_routes']);
48 }
49
50 /**
51 * Registers the routes for the objects of the controller.
52 *
53 * @since 4.7.0
54 *
55 * @see register_rest_route()
56 */
57 public function register_routes() {
58 register_rest_route(
59 $this->namespace,
60 '/' . $this->rest_base,
61 array(
62 array(
63 'methods' => WP_REST_Server::READABLE,
64 'callback' => array($this, 'get_items'),
65 'permission_callback' => array($this, 'get_items_permissions_check'),
66 // 'args' => $this->get_collection_params(),
67 ),
68 array(
69 'methods' => WP_REST_Server::CREATABLE,
70 'callback' => array($this, 'create_item'),
71 'permission_callback' => array($this, 'create_item_permissions_check'),
72 // 'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE),
73 ),
74 // 'schema' => array($this, 'get_public_item_schema'),
75 )
76 );
77
78 // $schema = $this->get_item_schema();
79 $get_item_args = array(
80 'context' => $this->get_context_param(array('default' => 'view')),
81 );
82
83 register_rest_route(
84 $this->namespace,
85 '/' . $this->rest_base . '/(?P<id>[\d]+)',
86 array(
87 'args' => array(
88 'id' => array(
89 'description' => __('Unique identifier for the object.', 'notificationx'),
90 'type' => 'integer',
91 ),
92 ),
93 array(
94 'methods' => WP_REST_Server::READABLE,
95 'callback' => array($this, 'get_item'),
96 'permission_callback' => array($this, 'get_item_permissions_check'),
97 // 'args' => $get_item_args,
98 ),
99 array(
100 'methods' => WP_REST_Server::EDITABLE,
101 'callback' => array($this, 'update_item'),
102 'permission_callback' => array($this, 'update_item_permissions_check'),
103 // 'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::EDITABLE),
104 ),
105 array(
106 'methods' => WP_REST_Server::DELETABLE,
107 'callback' => array($this, 'delete_item'),
108 'permission_callback' => array($this, 'delete_item_permissions_check'),
109 'args' => array(
110 'force' => array(
111 'type' => 'boolean',
112 'default' => false,
113 'description' => __('Whether to bypass Trash and force deletion.', 'notificationx'),
114 ),
115 ),
116 ),
117 // 'schema' => array($this, 'get_public_item_schema'),
118 )
119 );
120 }
121
122 /**
123 * Checks if a given request has access to read posts.
124 *
125 * @since 4.7.0
126 *
127 * @param WP_REST_Request $request Full details about the request.
128 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
129 */
130 public function get_items_permissions_check($request) {
131 return current_user_can('read_notificationx');
132 }
133
134 /**
135 * Checks if a given request has access to read post.
136 *
137 * @since 4.7.0
138 *
139 * @param WP_REST_Request $request Full details about the request.
140 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
141 */
142 public function get_item_permissions_check($request) {
143 $params = $request->get_params();
144 if( !empty( $params['source'] ) ) {
145 return current_user_can('read_notificationx');
146 }
147 return current_user_can('read_notificationx');
148 }
149
150
151 public function get_items($request) {
152 $params = $request->get_params();
153 $status = !empty($params['status']) ? $params['status'] : "all";
154 $page = !empty($params['page']) ? intval( $params['page'] ) : 1;
155 $per_page = !empty($params['per_page']) ? intval( $params['per_page'] ) : 20;
156 $search_keyword = !empty($params['s']) ? $params['s'] : '';
157 $start_from = ($page - 1) * $per_page;
158 $query = Database::get_instance()->query()
159 ->from('nx_posts a')
160 ->join('nx_stats b', 'b.nx_id', '=', 'a.nx_id')
161 ->group_by('a.nx_id')
162 ->order_by('a.updated_at', 'DESC')
163 ->select('a.*, SUM(b.clicks) clicks, SUM(b.views) views');
164 if ($status !== 'all') {
165 $query->where('enabled', $status == 'enabled' ? true : false);
166 }
167 if( $search_keyword ) {
168 $query->where(function($query) use ($search_keyword) {
169 $query->where('title', 'LIKE', '%' . $search_keyword . '%')
170 ->orWhere( 'a.nx_id', 'LIKE', '%'. $search_keyword . '%' );
171 });
172 }
173
174 $query->offset($start_from)
175 ->limit($per_page);
176 $posts = $query->get();
177 $posts = PostType::get_instance()->__get_posts( $posts, '*' );
178
179 // Add entries count for popup notifications
180 global $wpdb;
181 $entries_table = $wpdb->prefix . 'nx_entries';
182 // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- False positive: the query is prepared via $this->wpdb->prepare(), which this sniff does not recognise, and only $wpdb->prefix table names are interpolated. Audited 2026-07-16.
183 $entries_counts = $wpdb->get_results(
184 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- False positive: the query is prepared via $this->wpdb->prepare(), which this sniff does not recognise, and only $wpdb->prefix table names are interpolated. Audited 2026-07-16.
185 "SELECT nx_id, COUNT(*) as entries_count
186 FROM {$entries_table}
187 WHERE source IN ('popup_notification', 'exit_intent_custom')
188 GROUP BY nx_id",
189 ARRAY_A
190 );
191 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
192
193 // Create a lookup array for entries counts
194 $entries_lookup = [];
195 foreach ($entries_counts as $entry) {
196 $entries_lookup[$entry['nx_id']] = $entry['entries_count'];
197 }
198
199 // Add entries count to posts
200 foreach ($posts as $key => $post) {
201 if ($post['source'] === 'popup_notification') {
202 $posts[$key]['entries'] = isset($entries_lookup[$post['nx_id']]) ? $entries_lookup[$post['nx_id']] : 0;
203 }
204 }
205
206 $total_posts = Database::get_instance()->get_post(Database::$table_posts, [], 'count(*) AS total');
207 $enabled = Database::get_instance()->get_post(Database::$table_posts, ['enabled' => true], 'count(*) AS total');
208 $disabled = Database::get_instance()->get_post(Database::$table_posts, ['enabled' => false], 'count(*) AS total');
209
210 return [
211 'total' => $total_posts['total'],
212 'enabled' => $enabled['total'],
213 'disabled' => $disabled['total'],
214 'search_keyword' => $search_keyword,
215 'posts' => $posts,
216 ];
217
218 }
219
220 /**
221 * Retrieves a single post.
222 *
223 * @since 4.7.0
224 *
225 * @param WP_REST_Request $request Full details about the request.
226 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
227 */
228 public function get_item($request) {
229 PostType::get_instance()->set_context( 'edit' );
230 return PostType::get_instance()->get_post( absint( $request['id'] ) );
231 }
232
233 /**
234 * Checks if a given request has access to create a post.
235 *
236 * @since 4.7.0
237 *
238 * @param WP_REST_Request $request Full details about the request.
239 * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise.
240 */
241 public function create_item_permissions_check($request) {
242 if (!empty($request['id'])) {
243 return new WP_Error(
244 'rest_post_exists',
245 __('Cannot create existing post.', 'notificationx'),
246 array('status' => 400)
247 );
248 }
249
250 return current_user_can('edit_notificationx');
251 }
252
253 /**
254 * Creates a single post.
255 *
256 * @since 4.7.0
257 *
258 * @param WP_REST_Request $request Full details about the request.
259 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
260 */
261 public function create_item($request) {
262 if (!empty($request['nx_id'])) {
263 return new WP_Error(
264 'rest_post_exists',
265 __('Cannot create existing post.', 'notificationx'),
266 array('status' => 400)
267 );
268 }
269
270 // $prepared_post = $this->prepare_item_for_database($request);
271
272 // if (is_wp_error($prepared_post)) {
273 // return $prepared_post;
274 // }
275
276 $params = $request->get_params();
277 return PostType::get_instance()->save_post($params);
278 }
279
280 /**
281 * Checks if a given request has access to update a post.
282 *
283 * @since 4.7.0
284 *
285 * @param WP_REST_Request $request Full details about the request.
286 * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise.
287 */
288 public function update_item_permissions_check($request) {
289 $params = $request->get_params();
290 if( !empty( $params['source'] ) ) {
291 return current_user_can('edit_notificationx');
292 }
293 return current_user_can('edit_notificationx');
294 }
295
296 /**
297 * Updates a single post.
298 *
299 * @since 4.7.0
300 *
301 * @param WP_REST_Request $request Full details about the request.
302 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
303 */
304 public function update_item($request) {
305 $params = $request->get_params();
306 return PostType::get_instance()->save_post($params);
307 }
308
309 /**
310 * Checks if a given request has access to delete a post.
311 *
312 * @since 4.7.0
313 *
314 * @param WP_REST_Request $request Full details about the request.
315 * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise.
316 */
317 public function delete_item_permissions_check($request) {
318 // if ($post && !$this->check_delete_permission($post)) {
319 // return new WP_Error(
320 // 'rest_cannot_delete',
321 // __('Sorry, you are not allowed to delete this post.'),
322 // array('status' => rest_authorization_required_code())
323 // );
324 // }
325 return current_user_can('edit_notificationx');
326 }
327
328 /**
329 * Deletes a single post.
330 *
331 * @since 4.7.0
332 *
333 * @param WP_REST_Request $request Full details about the request.
334 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
335 */
336 public function delete_item($request) {
337 if(PostType::get_instance()->delete_post($request['id'])){
338 wp_send_json_success();
339 }
340 wp_send_json_error();
341 }
342
343 }
344