PluginProbe
F4 Post Tree / trunk
F4 Post Tree vtrunk
trunk 1.0.2 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.18 1.1.19 1.1.2 1.1.20 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 All 29 releases
f4-tree / Tree / Helpers.php

Helpers.php in F4 Post Tree trunk, at Tree/Helpers.php

394 lines 15.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace F4\TREE\Tree;
4
5 use F4\TREE\Core\Helpers as Core;
6
7 /**
8 * Tree Helpers
9 *
10 * All the WordPress helpers for the Tree module
11 *
12 * @since 1.0.0
13 * @package F4\TREE\Tree
14 */
15 class Helpers {
16 /**
17 * Check if tree is enabled on this screen
18 *
19 * @since 1.0.0
20 * @access public
21 * @static
22 * @return bool True if the tree is enabled in the current screen
23 */
24 public static function is_tree_enabled() {
25 global $current_screen;
26
27 $enabled_post_types = Core::get_settings('post-types');
28 $enabled_screen_ids = array();
29
30 foreach($enabled_post_types as $post_type_name => $post_type_enabled) {
31 if(post_type_exists($post_type_name) && $post_type_enabled == '1') {
32 $enabled_screen_ids[] = $post_type_name;
33 $enabled_screen_ids[] = 'edit-' . $post_type_name;
34 }
35 }
36
37 $is_enabled = in_array($current_screen->id, $enabled_screen_ids);
38 $is_enabled = apply_filters('F4/TREE/Tree/is_tree_enabled', $is_enabled, $current_screen);
39
40 return $is_enabled;
41 }
42
43 /**
44 * Check if tree is enabled for this post type
45 *
46 * @since 1.0.0
47 * @access public
48 * @static
49 * @return bool True if the tree is enabled for this post type
50 */
51 public static function is_tree_post_type($post_type) {
52 if(is_object($post_type)) {
53 $post_type = $post_type->post_type;
54 } elseif(is_numeric($post_type)) {
55 $post_id = $post_type;
56 $post_type = get_post_type($post_id);
57
58
59 if($post_type === 'revision') {
60 $post_type = get_post_type(wp_get_post_parent_id($post_id));
61 }
62 }
63
64 $enabled_post_types = Core::get_settings('post-types');
65 $enabled_post_types['nav_menu_item'] = '1';
66
67 $is_tree_post_type = isset($enabled_post_types[$post_type]);
68 $is_tree_post_type = apply_filters('F4/TREE/Tree/is_tree_post_type', $is_tree_post_type, $post_type);
69
70 return $is_tree_post_type;
71 }
72
73 /**
74 * Update changed timestamp
75 *
76 * @since 1.0.0
77 * @access public
78 * @static
79 * @return int The updated timestamp
80 */
81 public static function update_changed_timestamp($time = null) {
82 if(!$time) {
83 $time = time();
84 }
85
86 $time = apply_filters('F4/TREE/Tree/update_changed_timestamp', $time);
87
88 update_option('f4-tree-changed-timestamp', $time);
89
90 return $time;
91 }
92
93 /**
94 * Get changed timestamp
95 *
96 * @since 1.0.0
97 * @access public
98 * @static
99 * @return int The last changed timestamp
100 */
101 public static function get_changed_timestamp() {
102 $changed_timestamp = get_option('f4-tree-changed-timestamp', 0);
103 $changed_timestamp = apply_filters('F4/TREE/Tree/get_changed_timestamp', $changed_timestamp);
104
105 return $changed_timestamp;
106 }
107
108 /**
109 * Clear changed timestamp cache
110 *
111 * @since 1.0.0
112 * @access public
113 * @static
114 */
115 public static function clear_changed_timestamp_cache() {
116 wp_cache_delete('alloptions', 'options');
117 do_action('F4/TREE/Tree/clear_changed_timestamp_cache');
118 }
119
120 /**
121 * Get the icon for a node
122 *
123 * @since 1.0.0
124 * @access public
125 * @static
126 */
127 public static function get_node_icon($type, $object, $id, $status) {
128 // Icon: Default (external link)
129 $icon = array(
130 'html' => '<span class="fancytree-custom-icon-inline fancytree-custom-icon-status-' . $status . '">
131 <svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 100 100" xml:space="preserve">
132 <g>
133 <path d="M75.394,58.138l12.673-12.675c9.245-9.243,9.245-24.286,0-33.529c-9.244-9.246-24.286-9.246-33.53,0L36.248,30.223 c-9.245,9.243-9.245,24.286,0,33.529c1.365,1.366,2.859,2.524,4.44,3.486l9.791-9.792c-1.865-0.446-3.634-1.387-5.086-2.838 c-4.202-4.202-4.202-11.04,0-15.241l18.289-18.289c4.202-4.202,11.04-4.202,15.241,0c4.202,4.202,4.202,11.039,0,15.241 l-5.373,5.374C75.764,46.904,76.376,52.635,75.394,58.138z"></path>
134 <path d="M24.607,41.862L11.934,54.536c-9.246,9.244-9.246,24.286,0,33.53c9.243,9.245,24.286,9.245,33.53,0l18.288-18.289 c9.245-9.244,9.244-24.286,0-33.529c-1.364-1.366-2.858-2.524-4.439-3.486l-9.791,9.792c1.864,0.447,3.633,1.386,5.086,2.838 c4.202,4.202,4.202,11.039,0,15.241l-18.29,18.289c-4.202,4.202-11.039,4.202-15.241,0c-4.202-4.202-4.202-11.039,0-15.241 l5.374-5.373C24.236,53.097,23.624,47.365,24.607,41.862z"></path>
135 </g>
136 </svg>
137 </span>'
138 );
139
140 // Icon: Post types
141 if($type === 'post_type') {
142 if($object === 'page') {
143 // WooCommerce pages
144 // @todo: move to plugins hooks
145 if(function_exists('is_woocommerce')) {
146 if(wc_get_page_id('cart') == $id) {
147 // Cart
148 $icon = array(
149 'html' => '<span class="fancytree-custom-icon-inline fancytree-custom-icon-status-' . $status . '">
150 <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="shopping-cart" class="svg-inline--fa fa-shopping-cart fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M528.12 301.319l47.273-208C578.806 78.301 567.391 64 551.99 64H159.208l-9.166-44.81C147.758 8.021 137.93 0 126.529 0H24C10.745 0 0 10.745 0 24v16c0 13.255 10.745 24 24 24h69.883l70.248 343.435C147.325 417.1 136 435.222 136 456c0 30.928 25.072 56 56 56s56-25.072 56-56c0-15.674-6.447-29.835-16.824-40h209.647C430.447 426.165 424 440.326 424 456c0 30.928 25.072 56 56 56s56-25.072 56-56c0-22.172-12.888-41.332-31.579-50.405l5.517-24.276c3.413-15.018-8.002-29.319-23.403-29.319H218.117l-6.545-32h293.145c11.206 0 20.92-7.754 23.403-18.681z"></path></svg>
151 </span>'
152 );
153 } elseif(wc_get_page_id('checkout') == $id) {
154 // Checkout
155 $icon = array(
156 'html' => '<span class="fancytree-custom-icon-inline fancytree-custom-icon-status-' . $status . '">
157 <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="shopping-bag" class="svg-inline--fa fa-shopping-bag fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M352 160v-32C352 57.42 294.579 0 224 0 153.42 0 96 57.42 96 128v32H0v272c0 44.183 35.817 80 80 80h288c44.183 0 80-35.817 80-80V160h-96zm-192-32c0-35.29 28.71-64 64-64s64 28.71 64 64v32H160v-32zm160 120c-13.255 0-24-10.745-24-24s10.745-24 24-24 24 10.745 24 24-10.745 24-24 24zm-192 0c-13.255 0-24-10.745-24-24s10.745-24 24-24 24 10.745 24 24-10.745 24-24 24z"></path></svg>
158 </span>'
159 );
160 } elseif(wc_get_page_id('shop') == $id) {
161 // Shop
162 $icon = array(
163 'html' => '<span class="fancytree-custom-icon-inline fancytree-custom-icon-status-' . $status . '">
164 <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="store" class="svg-inline--fa fa-store fa-w-20" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 616 512"><path fill="currentColor" d="M602 118.6L537.1 15C531.3 5.7 521 0 510 0H106C95 0 84.7 5.7 78.9 15L14 118.6c-33.5 53.5-3.8 127.9 58.8 136.4 4.5.6 9.1.9 13.7.9 29.6 0 55.8-13 73.8-33.1 18 20.1 44.3 33.1 73.8 33.1 29.6 0 55.8-13 73.8-33.1 18 20.1 44.3 33.1 73.8 33.1 29.6 0 55.8-13 73.8-33.1 18.1 20.1 44.3 33.1 73.8 33.1 4.7 0 9.2-.3 13.7-.9 62.8-8.4 92.6-82.8 59-136.4zM529.5 288c-10 0-19.9-1.5-29.5-3.8V384H116v-99.8c-9.6 2.2-19.5 3.8-29.5 3.8-6 0-12.1-.4-18-1.2-5.6-.8-11.1-2.1-16.4-3.6V480c0 17.7 14.3 32 32 32h448c17.7 0 32-14.3 32-32V283.2c-5.4 1.6-10.8 2.9-16.4 3.6-6.1.8-12.1 1.2-18.2 1.2z"></path></svg>
165 </span>'
166 );
167 } elseif(wc_get_page_id('myaccount') == $id) {
168 // My Account
169 $icon = array(
170 'html' => '<span class="fancytree-custom-icon-inline fancytree-custom-icon-status-' . $status . '">
171 <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="user-circle" class="svg-inline--fa fa-user-circle fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 96c48.6 0 88 39.4 88 88s-39.4 88-88 88-88-39.4-88-88 39.4-88 88-88zm0 344c-58.7 0-111.3-26.6-146.5-68.2 18.8-35.4 55.6-59.8 98.5-59.8 2.4 0 4.8.4 7.1 1.1 13 4.2 26.6 6.9 40.9 6.9 14.3 0 28-2.7 40.9-6.9 2.3-.7 4.7-1.1 7.1-1.1 42.9 0 79.7 24.4 98.5 59.8C359.3 421.4 306.7 448 248 448z"></path></svg>
172 </span>'
173 );
174 } else {
175 $icon = array(
176 'html' => '<span class="fancytree-custom-icon-inline fancytree-custom-icon-status-' . $status . '">
177 <svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 300 300" xml:space="preserve">
178 <path d="M18.75,0v300H262.5V93.75h-93.75V0H18.75z M187.5,0v75h75L187.5,0z M56.25,75h75v18.75h-75V75z M56.25,131.25H225V150H56.25V131.25z M56.25,187.5H187.5v18.75H56.25V187.5z M56.25,243.75H225v18.75H56.25V243.75z"></path>
179 </svg>
180 </span>'
181 );
182 }
183 } else {
184 $icon = array(
185 'html' => '<span class="fancytree-custom-icon-inline fancytree-custom-icon-status-' . $status . '">
186 <svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 300 300" xml:space="preserve">
187 <path d="M18.75,0v300H262.5V93.75h-93.75V0H18.75z M187.5,0v75h75L187.5,0z M56.25,75h75v18.75h-75V75z M56.25,131.25H225V150H56.25V131.25z M56.25,187.5H187.5v18.75H56.25V187.5z M56.25,243.75H225v18.75H56.25V243.75z"></path>
188 </svg>
189 </span>'
190 );
191 }
192 } else {
193 $menu_icon = get_post_type_object($object)->menu_icon;
194 $menu_icon = !$menu_icon ? 'dashicons-admin-post' : $menu_icon;
195
196 $icon = array(
197 'html' => '<span class="dashicons-before ' . $menu_icon . ' fancytree-custom-icon-status-' . $status . '"></span>'
198 );
199 }
200
201 // Icon: Home
202 if($object === 'page') {
203 $page_on_front = (int)Core::maybe_translate_post_id(get_option('page_on_front'));
204
205 if($page_on_front && $id === $page_on_front) {
206 $icon = array(
207 'html' => '<span class="fancytree-custom-icon-inline fancytree-custom-icon-status-' . $status . '">
208 <svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 300 300" xml:space="preserve">
209 <path d="M300,162.504L150,0L0,162.504V300h125.001v-87.498h50.001V300H300V162.504z"></path>
210 </svg>
211 </span>'
212 );
213 }
214 }
215 } elseif($type === 'taxonomy') {
216 $icon = array(
217 'html' => '<span class="fancytree-custom-icon-inline fancytree-custom-icon-status-' . $status . '">
218 <svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 100 100" xml:space="preserve">
219 <path d="M93.423,45.799l-48.26,48.262c-2.855,2.854-7.487,2.851-10.338,0L6.094,65.327c-2.853-2.852-2.853-7.479,0-10.334 l48.262-48.26c1.609-1.609,3.779-2.278,5.881-2.073l-0.14-0.143l25.111,5.581L85.204,10.1c1.063,0.167,3.622,0.994,4.653,4.7 l5.164,23.075C96.096,40.516,95.563,43.658,93.423,45.799z M81.354,18.798c-2.977-2.974-7.794-2.974-10.763,0 c-2.977,2.975-2.977,7.792-0.007,10.765c2.976,2.976,7.793,2.976,10.77,0C84.33,26.59,84.33,21.772,81.354,18.798z"></path>
220 </svg>
221 </span>'
222 );
223 }
224
225 // Modify node icon
226 $icon = apply_filters('F4/TREE/Menu/get_node_icon', $icon, $type, $object, $id, $status);
227
228 return $icon;
229 }
230
231 /**
232 * Get tree node for a post
233 *
234 * @since 1.0.0
235 * @access public
236 * @static
237 */
238 public static function get_post_tree_node($post_item, $current_post_id) {
239 // Create default node
240 $node_item = array(
241 'key' => 'post-' . uniqid(),
242 'title' => (empty($post_item->post_title) ? __( '(no title)') : $post_item->post_title),
243 'tooltip' => 'ID: ' . $post_item->ID,
244 'icon' => self::get_node_icon('post_type', $post_item->post_type, $post_item->ID, $post_item->post_status),
245 'active' => ($post_item->ID == $current_post_id),
246 'expanded' => ($post_item->ID == $current_post_id),
247 'extraClasses' => array(),
248 'data' => array(
249 'url' => get_admin_url(null, 'post.php?post=' . $post_item->ID . '&action=edit'),
250 'type' => 'post',
251 'post_id' => $post_item->ID,
252 'post_type' => $post_item->post_type,
253 'post_status' => $post_item->post_status,
254 'allow_children' => false
255 )
256 );
257
258 // Disable drag and drop if no permission
259 if(!Core::current_user_can_post_cap('edit_post', $post_item->ID, $post_item->post_type)) {
260 $node_item['extraClasses'][] = 'node-disable-dnd';
261 }
262
263 // Add children if hierarchical
264 if(is_post_type_hierarchical($post_item->post_type)) {
265 $node_item['data']['allow_children'] = true;
266 $node_item['children'] = self::get_children($post_item->post_type, $post_item->ID, $current_post_id);
267 }
268
269 $node_item = apply_filters('F4/TREE/Tree/get_post_tree_node', $node_item, $post_item, $current_post_id);
270
271 return $node_item;
272 }
273
274 /**
275 * Get tree children
276 *
277 * @since 1.0.0
278 * @access public
279 * @static
280 */
281 public static function get_children($post_type = 'page', $post_parent = 0, $post_id = null, $recursive = true, $args = array()) {
282 if(!$post_id) {
283 $post_id = get_the_ID();
284 }
285
286 // Set defaults
287 $args = wp_parse_args(
288 $args,
289 array(
290 'suppress_filters' => false,
291 'nopaging' => true,
292 'orderby' => array(
293 'menu_order' => 'ASC',
294 'title' => 'ASC'
295 ),
296 'post_status' => array(
297 'draft',
298 'publish',
299 'future',
300 'pending',
301 'private'
302 )
303 )
304 );
305
306 // Force arguments
307 $args['post_parent'] = $post_parent;
308 $args['post_type'] = $post_type;
309
310 // Get posts
311 $posts = get_posts($args);
312
313 // Get tree nodes
314 $tree_nodes = array();
315
316 foreach($posts as $post_item) {
317 // Skip private posts if no permission
318 //if($post_item->post_status === 'private' && !Core::current_user_can_post_cap('read_private_posts', $post_item->ID, $post_item->post_type)) {
319 if($post_item->post_status === 'private' && !current_user_can('read_private_posts', $post_item->ID)) {
320 continue;
321 }
322
323 $tree_nodes[] = self::get_post_tree_node($post_item, $post_id);
324 }
325
326 return $tree_nodes;
327 }
328
329 /**
330 * Get the tree
331 *
332 * @since 1.0.0
333 * @access public
334 * @static
335 */
336 public static function get_tree($post_id, $post_type = 'page') {
337 // Get post type object
338 $post_type_object = get_post_type_object($post_type);
339
340 // Get child nodes
341 $post_nodes = self::get_children($post_type, 0, $post_id);
342 $post_nodes = apply_filters('F4/TREE/Tree/get_tree_post_nodes', $post_nodes, $post_id, $post_type, $post_type_object);
343
344 // Build tree
345 $tree_nodes = apply_filters('F4/TREE/Tree/get_tree_nodes_before', array(), $post_id, $post_type, $post_type_object, $post_nodes);
346
347 $tree_nodes[] = array(
348 'key' => 'pool-' . $post_type,
349 'title' => $post_type_object->label,
350 'expanded' => true,
351 'folder' => 1,
352 'unselectable' => 1,
353 'extraClasses' => 'node-disable-dnd tree-pool',
354 'children' => array_values($post_nodes),
355 'icon' => array(
356 'html' => '<span class="fancytree-custom-icon-inline">
357 <svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 108.2 108.2" xml:space="preserve">
358 <path d="M0,99.2h108.2l-0.9-79.7c-23.2,0-46.3,0-69.5,0V9.1H10.3L0.7,19.5L0,99.2z"></path>
359 </svg>
360 </span>'
361 ),
362 'tooltip' => $post_type_object->description,
363 'data' => array(
364 'type' => 'pool',
365 'allow_children' => true
366 )
367 );
368
369 $tree_nodes = apply_filters('F4/TREE/Tree/get_tree_nodes_after', $tree_nodes, $post_id, $post_type, $post_type_object, $post_nodes);
370 $tree_nodes = array_values($tree_nodes);
371
372 // Check for duplicate active nodes
373 $has_active_node = false;
374
375 array_walk_recursive($tree_nodes, function(&$v, $k) {
376 global $has_active_node;
377
378 if($k === 'active') {
379 if($has_active_node) {
380 $v = false;
381 }
382
383 if($v) {
384 $has_active_node = true;
385 }
386 }
387 });
388
389 return $tree_nodes;
390 }
391 }
392
393 ?>
394