PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.10
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.10
1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 All 34 releases
← All changes | includes/content-graph/window.php +119 -79 0.8.81.1.10 View file →
@@ -1,33 +1,81 @@
1 1 <?php
2 2 /**
3 - * Desktop Mode — Content Graph: window + desktop icon registration.
3 + * OpenStation — Content Graph: window + desktop icon registration.
4 4 *
5 5 * Filterable surface (mirrors the my-wordpress module shape):
6 6 *
7 - * - `desktop_mode_content_graph_window_args`
8 - * - `desktop_mode_content_graph_icon_args`
9 - * - `desktop_mode_content_graph_user_can_use`
10 - * - `desktop_mode_content_graph_post_types`
11 - * - `desktop_mode_content_graph_template_html`
7 + * - `openstation_content_graph_window_args`
8 + * - `openstation_content_graph_icon_args`
9 + * - `openstation_content_graph_user_can_use`
10 + * - `openstation_content_graph_post_types`
11 + * - `openstation_content_graph_template_html`
12 12 *
13 - * @package WPDesktopMode
14 - * @since 0.8.2
13 + * @package OpenStation
15 14 */
16 15
17 16 defined( 'ABSPATH' ) || exit;
18 17
19 18 /**
19 + * The Corkboard SVG, shared by the window icon and the desktop icon.
20 + *
21 + * The thread is the window's actual subject: the links between pieces
22 + * of content. That reading is unchanged and is why this icon exists at
23 + * all. What changed is everything drawn around it.
24 + *
25 + * The previous version framed two pinned notes with the thread arcing
26 + * over them. On a 64-unit grid the arc closed the top of the
27 + * silhouette, and a closed top over two rectangles is a bag: at 40px
28 + * and below the icon read as a shopping bag rather than a board. The
29 + * frame was also spending most of the 20px budget on an outline that
30 + * carried no meaning, leaving the notes too small to be notes.
31 + *
32 + * So the board and the paper are gone and the graph is the whole mark:
33 + * one focused post with related ones fanned around it, which is what
34 + * the window itself draws now that nodes are discs rather than post-
35 + * type glyphs (see `src/content-graph/satellites.ts`). Sizes are
36 + * deliberately unequal, so the hierarchy reads without a caption.
37 + *
38 + * Pin-led marks are deliberately avoided: `assets/images/pushpin.svg`
39 + * belongs to pinned notes, and an icon led by a pin would point at
40 + * that feature instead of this one.
41 + *
42 + * Drawn in `currentColor`, which makes it a silhouette: `renderIcon()`
43 + * paints it as a CSS mask rather than a background-image, so it takes
44 + * whatever colour the surface is already using for text. That keeps it
45 + * legible on the dark dock, on a light title bar, and under a desktop
46 + * theme's icon tint, with nothing to configure.
47 + *
48 + * Hand-placed at 64×64 like the Games icon, the established shape for
49 + * custom icons here, and held to five elements because it renders as
50 + * small as 20px in the dock.
51 + *
52 + * @return string Raw `<svg>` markup.
53 + */
54 +function openstation_content_graph_icon_svg() {
55 + return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">'
56 + // Threads first: the discs below are drawn over their ends, so
57 + // the joins stay round instead of showing a stroke cap.
58 + . '<path d="M14 16 32 32 52 18M32 32 40 49" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round"/>'
59 + // The focused post.
60 + . '<circle cx="32" cy="32" r="9" fill="currentColor"/>'
61 + // Its satellites, sized just under the hub so the eye lands on
62 + // the middle first.
63 + . '<circle cx="14" cy="16" r="5.5" fill="currentColor"/>'
64 + . '<circle cx="52" cy="18" r="5.5" fill="currentColor"/>'
65 + . '<circle cx="40" cy="49" r="5" fill="currentColor"/>'
66 + . '</svg>';
67 +}
68 +
69 +/**
20 70 * Whether the current user should see Content Graph.
21 71 *
22 72 * Mirrors the my-wordpress gate, anyone who can edit posts can view
23 73 * the link map of the content they author and maintain.
24 74 *
25 - * @since 0.8.2
26 - *
27 75 * @return bool
28 76 */
29 -function desktop_mode_content_graph_user_can_use() {
77 +function openstation_content_graph_user_can_use() {
30 78 $can = current_user_can( 'edit_posts' );
31 79
32 80 /**
33 81 * Filter whether the current user can see the Content Graph
@@ -32,13 +80,11 @@
32 80 /**
33 81 * Filter whether the current user can see the Content Graph
34 82 * desktop icon and window.
35 83 *
36 - * @since 0.8.2
37 - *
38 84 * @param bool $can Default: edit_posts capability.
39 85 */
40 - return (bool) apply_filters( 'desktop_mode_content_graph_user_can_use', $can );
86 + return (bool) apply_filters( 'openstation_content_graph_user_can_use', $can );
41 87 }
42 88
43 89 /**
44 90 * Build the descriptor list of post types eligible for the graph.
@@ -45,13 +91,11 @@
45 91 * Defaults to every public post type (so CPTs participate by
46 92 * default), matching the user-facing filter bar that ships ON for all
47 93 * of them.
48 94 *
49 - * @since 0.8.2
50 - *
51 - * @return array[] Each entry: `array( 'slug', 'label', 'icon' )`.
95 + * @return array[] Each entry: `array( 'slug', 'label', 'icon', 'taxonomies' )`.
52 96 */
53 -function desktop_mode_content_graph_post_types() {
97 +function openstation_content_graph_post_types() {
54 98 $types = get_post_types( array( 'public' => true ), 'objects' );
55 99 $result = array();
56 100 foreach ( $types as $type ) {
57 101 // `attachment` is public but participates in the graph as media
@@ -60,46 +104,59 @@
60 104 if ( 'attachment' === $type->name ) {
61 105 continue;
62 106 }
63 107 $result[] = array(
64 - 'slug' => (string) $type->name,
65 - 'label' => (string) $type->labels->name,
66 - 'icon' => (string) ( ! empty( $type->menu_icon ) ? $type->menu_icon : 'dashicons-admin-post' ),
108 + 'slug' => (string) $type->name,
109 + 'label' => (string) $type->labels->name,
110 + 'icon' => (string) ( ! empty( $type->menu_icon ) ? $type->menu_icon : 'dashicons-admin-post' ),
111 + 'taxonomies' => array(
112 + 'category' => is_object_in_taxonomy( $type->name, 'category' ),
113 + 'post_tag' => is_object_in_taxonomy( $type->name, 'post_tag' ),
114 + ),
67 115 );
68 116 }
69 117
70 118 /**
71 119 * Filter the list of post types shown in the Content Graph filter
72 - * bar. Each entry must declare `slug`, `label`, and `icon`. Removing
120 + * bar. Each entry declares `slug`, `label`, `icon`, and optionally
121 + * `taxonomies` (`array( 'category' => bool, 'post_tag' => bool )`);
122 + * entries missing `taxonomies` get it derived from
123 + * `is_object_in_taxonomy()` after filtering. Removing
73 124 * an entry hides it from the filter bar AND excludes it from the
74 125 * graph entirely.
75 126 *
76 - * @since 0.8.2
77 - *
78 127 * @param array[] $result Default: every public post type except attachment.
79 128 */
80 - $filtered = apply_filters( 'desktop_mode_content_graph_post_types', $result );
81 - return is_array( $filtered ) ? array_values( $filtered ) : $result;
129 + $filtered = apply_filters( 'openstation_content_graph_post_types', $result );
130 + $filtered = is_array( $filtered ) ? array_values( $filtered ) : $result;
131 +
132 + foreach ( $filtered as $i => $entry ) {
133 + $slug = isset( $entry['slug'] ) ? (string) $entry['slug'] : '';
134 + $filtered[ $i ]['taxonomies'] = array(
135 + 'category' => isset( $entry['taxonomies'] ) ? ! empty( $entry['taxonomies']['category'] ) : is_object_in_taxonomy( $slug, 'category' ),
136 + 'post_tag' => isset( $entry['taxonomies'] ) ? ! empty( $entry['taxonomies']['post_tag'] ) : is_object_in_taxonomy( $slug, 'post_tag' ),
137 + );
138 + }
139 +
140 + return $filtered;
82 141 }
83 142
84 143 /**
85 144 * Render the Content Graph window's static template body. The bundle
86 - * mounts its UI into `[data-desktop-mode-content-graph-root]`.
87 - *
88 - * @since 0.8.2
145 + * mounts its UI into `[data-os-content-graph-root]`.
89 146 */
90 -function desktop_mode_content_graph_render_template() {
147 +function openstation_content_graph_render_template() {
91 148 ob_start();
92 149 ?>
93 - <div class="desktop-mode-content-graph" data-desktop-mode-content-graph-root>
94 - <header class="desktop-mode-content-graph__toolbar" data-desktop-mode-content-graph-toolbar></header>
95 - <div class="desktop-mode-content-graph__body">
96 - <div class="desktop-mode-content-graph__stage" data-desktop-mode-content-graph-stage>
97 - <div class="desktop-mode-content-graph__loading" data-desktop-mode-content-graph-loading>
98 - <wpd-spinner></wpd-spinner>
150 + <div class="desktop-mode-content-graph" data-os-content-graph-root>
151 + <header class="os-content-graph__toolbar" data-os-content-graph-toolbar></header>
152 + <div class="os-content-graph__body">
153 + <div class="os-content-graph__stage" data-os-content-graph-stage>
154 + <div class="os-content-graph__loading" data-os-content-graph-loading>
155 + <os-spinner></os-spinner>
99 156 </div>
100 157 </div>
101 - <aside class="desktop-mode-content-graph__panel" data-desktop-mode-content-graph-panel hidden></aside>
158 + <aside class="os-content-graph__panel" data-os-content-graph-panel hidden></aside>
102 159 </div>
103 160 </div>
104 161 <?php
105 162 $html = (string) ob_get_clean();
@@ -106,16 +163,14 @@
106 163
107 164 /**
108 165 * Filter the Content Graph window's template HTML.
109 166 *
110 - * @since 0.8.2
111 - *
112 167 * @param string $html Default template HTML.
113 168 */
114 - $filtered = (string) apply_filters( 'desktop_mode_content_graph_template_html', $html );
169 + $filtered = (string) apply_filters( 'openstation_content_graph_template_html', $html );
115 170
116 - $allowed_html = function_exists( 'desktop_mode_native_window_allowed_html' )
117 - ? desktop_mode_native_window_allowed_html()
171 + $allowed_html = function_exists( 'openstation_native_window_allowed_html' )
172 + ? openstation_native_window_allowed_html()
118 173 : wp_kses_allowed_html( 'post' );
119 174
120 175 echo wp_kses( $filtered, $allowed_html );
121 176 }
@@ -122,22 +177,22 @@
122 177
123 178 /**
124 179 * Register the native window + the desktop icon on `init` priority 20,
125 180 * matching the my-wordpress + recycle-bin modules.
126 - *
127 - * @since 0.8.2
128 181 */
129 -function desktop_mode_content_graph_register_window() {
130 - if ( ! desktop_mode_content_graph_user_can_use() ) {
182 +function openstation_content_graph_register_window() {
183 + if ( ! openstation_content_graph_user_can_use() ) {
131 184 return;
132 185 }
133 186
187 + $icon_uri = 'data:image/svg+xml;base64,' . base64_encode( openstation_content_graph_icon_svg() );
188 +
134 189 $window_args = array(
135 - 'title' => __( 'Content Graph', 'desktop-mode' ),
136 - 'icon' => 'dashicons-networking',
137 - 'template' => 'desktop_mode_content_graph_render_template',
190 + 'title' => __( 'Corkboard', 'desktop-mode' ),
191 + 'icon' => $icon_uri,
192 + 'template' => 'openstation_content_graph_render_template',
138 193 'script' => 'desktop-mode-content-graph',
139 - 'style' => 'desktop-mode-content-graph',
194 + 'styles' => array( 'desktop-mode-content-graph' ),
140 195 'width' => 1080,
141 196 'height' => 720,
142 197 'min_width' => 720,
143 198 'min_height' => 480,
@@ -150,9 +205,12 @@
150 205 'editTermUrl' => esc_url_raw( admin_url( 'term.php' ) ),
151 206 'editUserUrl' => esc_url_raw( admin_url( 'user-edit.php' ) ),
152 207 'editCommentUrl' => esc_url_raw( admin_url( 'comment.php' ) ),
153 208 'mediaUrl' => esc_url_raw( admin_url( 'upload.php' ) ),
154 - 'postTypes' => desktop_mode_content_graph_post_types(),
209 + // Labels the "Open in <site>" action on the detail panel,
210 + // which hands off to the WP Explorer window.
211 + 'siteName' => openstation_site_title(),
212 + 'postTypes' => openstation_content_graph_post_types(),
155 213 ),
156 214 );
157 215
158 216 /**
@@ -157,24 +215,22 @@
157 215
158 216 /**
159 217 * Filter the args used to register the Content Graph native window.
160 218 *
161 - * @since 0.8.2
162 - *
163 - * @param array $window_args Args passed to `desktop_mode_register_window()`.
219 + * @param array $window_args Args passed to `openstation_register_window()`.
164 220 */
165 - $window_args = (array) apply_filters( 'desktop_mode_content_graph_window_args', $window_args );
221 + $window_args = (array) apply_filters( 'openstation_content_graph_window_args', $window_args );
166 222
167 - $registered = desktop_mode_register_window( 'desktop-mode-content-graph', $window_args );
223 + $registered = openstation_register_window( 'desktop-mode-content-graph', $window_args );
168 224 if ( is_wp_error( $registered ) ) {
169 225 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
170 - error_log( '[desktop-mode] Content Graph window registration failed: ' . $registered->get_error_message() );
226 + error_log( '[openstation] Content Graph window registration failed: ' . $registered->get_error_message() );
171 227 return;
172 228 }
173 229
174 230 $icon_args = array(
175 - 'title' => __( 'Content Graph', 'desktop-mode' ),
176 - 'icon' => 'dashicons-networking',
231 + 'title' => __( 'Corkboard', 'desktop-mode' ),
232 + 'icon_svg' => openstation_content_graph_icon_svg(),
177 233 'window' => 'desktop-mode-content-graph',
178 234 'pinned' => false,
179 235 'position' => 20,
180 236 );
@@ -181,27 +237,11 @@
181 237
182 238 /**
183 239 * Filter the args used to register the Content Graph desktop icon.
184 240 *
185 - * @since 0.8.2
186 - *
187 - * @param array $icon_args Args passed to `desktop_mode_register_icon()`.
241 + * @param array $icon_args Args passed to `openstation_register_icon()`.
188 242 */
189 - $icon_args = (array) apply_filters( 'desktop_mode_content_graph_icon_args', $icon_args );
243 + $icon_args = (array) apply_filters( 'openstation_content_graph_icon_args', $icon_args );
190 244
191 - desktop_mode_register_icon( 'desktop-mode-content-graph', $icon_args );
245 + openstation_register_icon( 'desktop-mode-content-graph', $icon_args );
192 246 }
193 -add_action( 'init', 'desktop_mode_content_graph_register_window', 20 );
194 -
195 -/**
196 - * Enqueue the bundle's CSS in admin context. The script is lazy-
197 - * loaded by the native-window sync.
198 - *
199 - * @since 0.8.2
200 - */
201 -function desktop_mode_content_graph_enqueue_styles() {
202 - if ( ! desktop_mode_content_graph_user_can_use() ) {
203 - return;
204 - }
205 - wp_enqueue_style( 'desktop-mode-content-graph' );
206 -}
207 -add_action( 'admin_enqueue_scripts', 'desktop_mode_content_graph_enqueue_styles', 30 );
247 +add_action( 'init', 'openstation_content_graph_register_window', 20 );