PluginProbe
Assistant – Every Day Productivity Apps / 0.5.0
Assistant – Every Day Productivity Apps v0.5.0
1.5.5 trunk 0.1.0 0.2.0 0.2.1 0.2.2 0.3.0 0.3.1 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.6.0 0.7.0 0.7.0.2 0.7.0.3 0.7.0.4 0.7.0.5 0.7.0.6 0.7.0.7 0.7.0.8 0.7.0.9 0.7.1 1.0 All 71 releases
assistant / backend / src / Controllers / PostsController.php

PostsController.php in Assistant – Every Day Productivity Apps 0.5.0, at backend/src/Controllers/PostsController.php

445 lines 10.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FL\Assistant\Controllers;
4
5 use FL\Assistant\Data\Repository\LabelsRepository;
6 use FL\Assistant\Data\Repository\PostsRepository;
7 use FL\Assistant\Data\Transformers\PostTransformer;
8 use FL\Assistant\System\Contracts\ControllerAbstract;
9
10 use WP_REST_Request;
11 use WP_REST_Server;
12
13 /**
14 * REST API logic for posts.
15 */
16 class PostsController extends ControllerAbstract {
17
18 protected $labels;
19 protected $posts;
20 protected $transformer;
21
22 public function __construct(
23 LabelsRepository $labels,
24 PostsRepository $posts,
25 PostTransformer $transformer
26 ) {
27 $this->labels = $labels;
28 $this->posts = $posts;
29 $this->transformer = $transformer;
30 }
31
32 /**
33 * Register routes.
34 */
35 public function register_routes() {
36 $this->route(
37 '/posts',
38 [
39 [
40 'methods' => WP_REST_Server::READABLE,
41 'callback' => [ $this, 'posts' ],
42 'permission_callback' => function () {
43 return current_user_can( 'edit_others_posts' );
44 },
45 ],
46 [
47 'methods' => WP_REST_Server::CREATABLE,
48 'callback' => [ $this, 'create_post' ],
49 'permission_callback' => function () {
50 return current_user_can( 'edit_others_posts' );
51 },
52 ],
53 ]
54 );
55
56 $this->route(
57 '/posts/hierarchical',
58 [
59 [
60 'methods' => WP_REST_Server::READABLE,
61 'callback' => [ $this, 'hierarchical_posts' ],
62 'permission_callback' => function () {
63 return current_user_can( 'edit_others_posts' );
64 },
65 ],
66 ]
67 );
68
69 $this->route(
70 '/posts/count',
71 [
72 [
73 'methods' => WP_REST_Server::READABLE,
74 'callback' => [ $this, 'posts_count' ],
75 'permission_callback' => function () {
76 return current_user_can( 'edit_others_posts' );
77 },
78 ],
79 ]
80 );
81
82 $this->route(
83 '/posts/(?P<id>\d+)',
84 [
85 [
86 'methods' => WP_REST_Server::READABLE,
87 'callback' => [ $this, 'post' ],
88 'args' => [
89 'id' => [
90 'required' => true,
91 'type' => 'number',
92 ],
93 ],
94 'permission_callback' => function () {
95 return current_user_can( 'edit_others_posts' );
96 },
97 ],
98 [
99 'methods' => WP_REST_Server::CREATABLE,
100 'callback' => [ $this, 'update_post' ],
101 'args' => [
102 'id' => [
103 'required' => true,
104 'type' => 'number',
105 ],
106 'action' => [
107 'required' => true,
108 'type' => 'string',
109 ],
110 ],
111 'permission_callback' => function () {
112 return current_user_can( 'edit_others_posts' );
113 },
114 ],
115 [
116 'methods' => WP_REST_Server::DELETABLE,
117 'callback' => [ $this, 'delete_post' ],
118 'args' => [
119 'id' => [
120 'required' => true,
121 'type' => 'number',
122 ],
123 ],
124 'permission_callback' => function () {
125 return current_user_can( 'edit_others_posts' );
126 },
127 ],
128 ]
129 );
130
131 $this->route(
132 '/posts/(?P<id>\d+)/clone',
133 [
134 [
135 'methods' => WP_REST_Server::CREATABLE,
136 'callback' => [ $this, 'clone_post' ],
137 'args' => [
138 'id' => [
139 'required' => true,
140 'type' => 'number',
141 ],
142 ],
143 'permission_callback' => function () {
144 return current_user_can( 'edit_others_posts' );
145 },
146 ],
147 ]
148 );
149 }
150
151 /**
152 * Returns an array of posts and related data.
153 */
154 public function posts( WP_REST_Request $request ) {
155
156 $params = $request->get_params();
157 $params['perm'] = 'editable';
158
159 if ( isset( $params['label'] ) && $params['label'] ) {
160 $params['post__in'] = $this->labels->get_object_ids( 'post', $params['label'] );
161 if ( ! count( $params['post__in'] ) ) {
162 $params['post__in'][] = -1; // post__in returns all posts if empty.
163 }
164 }
165
166 $pager = $this->posts->paginate( $params, $this->transformer );
167
168 return rest_ensure_response( $pager->to_array() );
169 }
170
171 /**
172 * Returns an array of posts and related data
173 * with child posts contained in the parent
174 * post's data array.
175 */
176 public function hierarchical_posts( $request ) {
177 $response = [];
178 $children = [];
179 $params = $request->get_params();
180 $posts = get_posts(
181 array_merge(
182 $params,
183 [
184 'perm' => 'editable',
185 ]
186 )
187 );
188
189 foreach ( $posts as $post ) {
190 if ( $post->post_parent ) {
191 if ( ! isset( $children[ $post->post_parent ] ) ) {
192 $children[ $post->post_parent ] = [];
193 }
194 $children [ $post->post_parent ][] = $post;
195 }
196 }
197
198 foreach ( $posts as $post ) {
199 if ( ! $post->post_parent ) {
200 $parent = $this->transform( $post );
201 $parent['children'] = $this->get_child_posts( $post, $children );
202 $response[] = $parent;
203 }
204 }
205
206 return rest_ensure_response( $response );
207 }
208
209 /**
210 * Returns an array of response data for a single post.
211 */
212 public function transform( $post ) {
213 return call_user_func( $this->transformer, $post );
214 }
215
216 /**
217 * Returns an array of child posts for the given post.
218 * A $children array must be passed to search for children.
219 */
220 public function get_child_posts( $post, $children ) {
221 if ( isset( $children[ $post->ID ] ) ) {
222 $post_children = $children[ $post->ID ];
223 foreach ( $post_children as $i => $child ) {
224 $post_children[ $i ] = $this->transform( $child );
225 $post_children[ $i ]['children'] = $this->get_child_posts( $child, $children );
226 }
227
228 return $post_children;
229 }
230
231 return [];
232 }
233
234 /**
235 * Returns an array of counts by post type.
236 */
237 public function posts_count( $request ) {
238
239 $post_types = $this->posts->get_types();
240 $response = [];
241
242 foreach ( $post_types as $slug => $label ) {
243 $counts = wp_count_posts( $slug );
244 $counts->total = $counts->publish + $counts->draft + $counts->pending + $counts->private + $counts->future;
245 $response[ $slug ] = $counts;
246 }
247
248 return rest_ensure_response( $response );
249 }
250
251 /**
252 * Returns data for a single post.
253 */
254 public function post( $request ) {
255 $id = $request->get_param( 'id' );
256
257 if ( current_user_can( 'edit_post', $id ) ) {
258 $post = get_post( $id );
259
260 return $this->transform( $post );
261 }
262
263 return [];
264 }
265
266 /**
267 * Creates a single post.
268 */
269 public function create_post( $request ) {
270 $id = wp_insert_post( $request->get_params() );
271
272 if ( ! $id || is_wp_error( $id ) ) {
273 return [
274 'error' => true,
275 ];
276 }
277
278 return $this->transform( get_post( $id ) );
279 }
280
281 /**
282 * Clones a single post.
283 */
284 public function clone_post( $request ) {
285 global $wpdb;
286
287 $post_id = absint( $request->get_param( 'id' ) );
288 $post = get_post( $post_id );
289 $current_user = wp_get_current_user();
290 $post_data = [
291 'comment_status' => $post->comment_status,
292 'ping_status' => $post->ping_status,
293 'post_author' => $current_user->ID,
294 'post_content' => $post->post_content,
295 'post_excerpt' => $post->post_excerpt,
296 'post_name' => $post->post_name . '-copy',
297 'post_parent' => $post->post_parent,
298 'post_password' => $post->post_password,
299 'post_status' => 'draft',
300 /* translators: %s: post/page title */
301 'post_title' => sprintf( _x( '%s - Copy', '%s stands for post/page title.', 'fl-assistant' ), $post->post_title ),
302 'post_type' => $post->post_type,
303 'to_ping' => $post->to_ping,
304 'menu_order' => $post->menu_order,
305 ];
306
307 $new_post_id = wp_insert_post( $post_data );
308 $post_meta = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM {$wpdb->postmeta} WHERE post_id = %d", $post_id ) );
309 $taxonomies = get_object_taxonomies( $post->post_type );
310
311 if ( count( $post_meta ) !== 0 ) {
312 foreach ( $post_meta as $meta_info ) {
313 $meta_key = $meta_info->meta_key;
314 $meta_value = addslashes( $meta_info->meta_value );
315 $wpdb->query( "INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) values ({$new_post_id}, '{$meta_key}', '{$meta_value}')" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
316 }
317 }
318
319 foreach ( $taxonomies as $taxonomy ) {
320 $post_terms = wp_get_object_terms( $post_id, $taxonomy );
321 for ( $i = 0; $i < count( $post_terms ); $i++ ) {
322 wp_set_object_terms( $new_post_id, $post_terms[ $i ]->slug, $taxonomy, true );
323 }
324 }
325
326 return $this->transform( get_post( $new_post_id ) );
327 }
328
329 /**
330 * Updates a single post based on the specified action.
331 */
332 public function update_post( $request ) {
333 $id = $request->get_param( 'id' );
334 $action = $request->get_param( 'action' );
335
336 if ( ! current_user_can( 'edit_post', $id ) ) {
337 return rest_ensure_response(
338 [
339 'error' => true,
340 ]
341 );
342 }
343
344 switch ( $action ) {
345 case 'data':
346 $data = (array) $request->get_param( 'data' );
347 if ( isset( $data['meta'] ) ) {
348 $this->update_post_meta( $id, $data['meta'] );
349 unset( $data['meta'] );
350 }
351 if ( isset( $data['terms'] ) ) {
352 $this->update_post_terms( $id, $data['terms'] );
353 unset( $data['terms'] );
354 }
355 if ( isset( $data['thumbnail'] ) ) {
356 if ( '0' === $data['thumbnail'] ) {
357 delete_post_meta( $id, '_thumbnail_id' );
358 } else {
359 set_post_thumbnail( $id, $data['thumbnail'] );
360 }
361
362 unset( $data['thumbnail'] );
363 }
364 wp_update_post(
365 array_merge(
366 $data,
367 [
368 'ID' => $id,
369 ]
370 )
371 );
372 break;
373 case 'meta':
374 $data = (array) $request->get_param( 'data' );
375 $this->update_post_meta( $id, $data );
376 break;
377 case 'terms':
378 $data = (array) $request->get_param( 'data' );
379 $this->update_post_terms( $id, $data );
380 break;
381 case 'trash':
382 if ( ! EMPTY_TRASH_DAYS ) {
383 wp_delete_post( $id );
384 } else {
385 wp_trash_post( $id );
386 }
387 break;
388 case 'untrash':
389 wp_untrash_post( $id );
390 break;
391
392 }
393
394 $updated_post = get_post( $id );
395
396 return rest_ensure_response(
397 [
398 'success' => true,
399 'post' => $updated_post ? $this->transform( $updated_post ) : null,
400 ]
401 );
402 }
403
404 /**
405 * Updates post meta values for a post.
406 */
407 public function update_post_meta( $id, $meta ) {
408 foreach ( $meta as $key => $value ) {
409 update_post_meta( $id, $key, $value );
410 }
411 }
412
413 /**
414 * Updates terms for a post.
415 */
416 public function update_post_terms( $id, $terms ) {
417 foreach ( $terms as $taxonomy => $ids ) {
418 wp_set_post_terms( $id, $ids, $taxonomy, false );
419 }
420 }
421
422 /**
423 * Deletes a single post based on the specified ID.
424 */
425 public function delete_post( $request ) {
426 $id = $request->get_param( 'id' );
427
428 if ( ! current_user_can( 'edit_post', $id ) ) {
429 return rest_ensure_response(
430 [
431 'error' => true,
432 ]
433 );
434 }
435
436 wp_delete_post( $id );
437
438 return rest_ensure_response(
439 [
440 'success' => true,
441 ]
442 );
443 }
444 }
445