| 1 |
<?php |
| 2 |
/** |
| 3 |
* My WordPress — the content explorer, as an OpenStation app. |
| 4 |
* |
| 5 |
* The full WP Explorer surface on the App Framework, split the way |
| 6 |
* the framework splits: the PHP half is the window and the truth, the |
| 7 |
* BODY lives in `my-wordpress.os.ts` beside it — a client view where |
| 8 |
* selection, infinite scroll, drag-out, the context menu, media zoom |
| 9 |
* and every repaint are instant. `watch( '*' )` repaints the window |
| 10 |
* whenever any other window changes any content. |
| 11 |
* |
| 12 |
* THIS file is deliberately just the composition: the declaration, |
| 13 |
* the state schema, and the wiring of actions to their handlers. The |
| 14 |
* substance lives in focused parts beside it (plain `.php` on purpose |
| 15 |
* — only `*.os.php` files are app entries to the framework loader; |
| 16 |
* see "Splitting a large app" in `docs/app-framework.md`): |
| 17 |
* sections.php (what the explorer OFFERS — builtins + discovered CPTs |
| 18 |
* with plugin-group folders + Agents, sorts), lists.php (what a |
| 19 |
* section CONTAINS — queries, counts, per-item authorization, the |
| 20 |
* dossier), dossiers.php (what a post OPENS INTO — relation folders, |
| 21 |
* sub-lists, stats panes, edit choices, preview actions), actions.php |
| 22 |
* (what a dispatch DOES), agents.php (the Agents payload + |
| 23 |
* mutations), woocommerce.php (Orders + Customers, inert without |
| 24 |
* WooCommerce), payload.php (the data payload, one function). |
| 25 |
* |
| 26 |
* Plugin surfaces are shared with the original explorer, not forked: |
| 27 |
* CPT discovery honours `openstation_my_wordpress_post_types` / |
| 28 |
* `_post_type_entity` / `_post_type_groups`; the preview-action |
| 29 |
* pipeline consumes the same `openstation_my_wordpress_preview_actions` |
| 30 |
* descriptors and `os.my-wordpress.preview-actions` JS filter; the |
| 31 |
* Agents section runs through the same `openstation_agent_*` store, |
| 32 |
* draft, identity and catalogue functions the `/desktop-mode/v1/agents` |
| 33 |
* routes wrap. This app IS WP Explorer now — the legacy window |
| 34 |
* (`desktop-mode-my-wordpress`) is gone, and the app carries its |
| 35 |
* name, icon, pinned launcher slot, and every surface. |
| 36 |
* |
| 37 |
* (Header kept short on purpose: Plugin Check's direct-access scan |
| 38 |
* reads only the first 50 raw lines, and the guard below must land |
| 39 |
* inside that window — it cannot precede the `namespace` statement.) |
| 40 |
* |
| 41 |
* @package OpenStation |
| 42 |
*/ |
| 43 |
|
| 44 |
namespace OpenStation\Apps\MyWordPress; |
| 45 |
|
| 46 |
use OpenStation\App; |
| 47 |
use OpenStation\App\State; |
| 48 |
|
| 49 |
// Direct access, unless a standalone host is booting on bare PHP. |
| 50 |
if ( ! defined( 'ABSPATH' ) ) { |
| 51 |
defined( 'OPENSTATION_STANDALONE' ) || exit; |
| 52 |
} |
| 53 |
|
| 54 |
require_once __DIR__ . '/parts/woocommerce.php'; |
| 55 |
require_once __DIR__ . '/parts/sections.php'; |
| 56 |
require_once __DIR__ . '/parts/lists.php'; |
| 57 |
require_once __DIR__ . '/parts/dossiers.php'; |
| 58 |
require_once __DIR__ . '/parts/actions.php'; |
| 59 |
require_once __DIR__ . '/parts/agents.php'; |
| 60 |
require_once __DIR__ . '/parts/payload.php'; |
| 61 |
|
| 62 |
return App::define( 'my-wordpress' ) |
| 63 |
// The app IS WP Explorer now: it wears the original's name, its |
| 64 |
// folder-with-mark art, and its pinned launcher slot. The helpers |
| 65 |
// stay in `includes/my-wordpress/window.php` (that module keeps |
| 66 |
// hosting the detail/footprint surfaces, launcher-less); the |
| 67 |
// guards cover a standalone host where they don't load. |
| 68 |
->title( |
| 69 |
function_exists( 'openstation_my_wordpress_app_title' ) |
| 70 |
? openstation_my_wordpress_app_title() |
| 71 |
: __( 'WP Explorer', 'desktop-mode' ) |
| 72 |
) |
| 73 |
->icon( |
| 74 |
function_exists( 'openstation_my_wordpress_icon_svg' ) |
| 75 |
? openstation_my_wordpress_icon_svg() |
| 76 |
: ICON |
| 77 |
) |
| 78 |
->size( 960, 640 ) |
| 79 |
->min_size( 640, 420 ) |
| 80 |
->placement( 'none' ) |
| 81 |
->desktop_icon( |
| 82 |
array( |
| 83 |
'position' => -1, |
| 84 |
'pinned' => true, |
| 85 |
) |
| 86 |
) |
| 87 |
->capabilities( 'edit_posts' ) |
| 88 |
->watch( '*' ) |
| 89 |
->state( |
| 90 |
array( |
| 91 |
'group' => '', |
| 92 |
'section' => '', |
| 93 |
'item' => 0, |
| 94 |
'into' => 0, |
| 95 |
'relation' => '', |
| 96 |
// The activity footprint: whose fills the body (0 = closed), |
| 97 |
// and their name for the breadcrumb before the payload lands. |
| 98 |
'footprint' => 0, |
| 99 |
'fpName' => '', |
| 100 |
'query' => '', |
| 101 |
'page' => 1, |
| 102 |
'sort' => '', |
| 103 |
'selected' => array(), |
| 104 |
// How a section lists: the tile canvas (`icons`) or the |
| 105 |
// sortable table (`list`). Remembered per user — restored |
| 106 |
// on mount, saved by the `view` action. |
| 107 |
'view' => 'icons', |
| 108 |
// The Agents section. `item` doubles as the selected agent; |
| 109 |
// the rest is the wizard: which detail tab is open, whether |
| 110 |
// the create flow is on and at which station, the agent |
| 111 |
// taking shape in it (an untyped slot — the client rolls |
| 112 |
// its face and its seeds, the server drafts into it and |
| 113 |
// creates from it), and the two message rails the original |
| 114 |
// kept in renderer state. |
| 115 |
'pane' => 'define', |
| 116 |
'casting' => false, |
| 117 |
'wstep' => 0, |
| 118 |
'cast' => null, |
| 119 |
'agentNotice' => '', |
| 120 |
'briefError' => '', |
| 121 |
) |
| 122 |
) |
| 123 |
->title_bar_button( |
| 124 |
'refresh', |
| 125 |
array( |
| 126 |
'label' => __( 'Refresh', 'desktop-mode' ), |
| 127 |
'icon' => 'reload', |
| 128 |
'action' => 'refresh', |
| 129 |
) |
| 130 |
) |
| 131 |
// `refresh` is the framework's built-in: recompute data(), re-render. |
| 132 |
// The remembered view mode lands before the first paint. |
| 133 |
->mount( __NAMESPACE__ . '\mount' ) |
| 134 |
// Navigation — parts/actions.php. |
| 135 |
->action( 'go', __NAMESPACE__ . '\go_action' ) |
| 136 |
->action( 'back', __NAMESPACE__ . '\back_action' ) |
| 137 |
->action( 'open', __NAMESPACE__ . '\open_action' ) |
| 138 |
->action( 'into', __NAMESPACE__ . '\into_action' ) |
| 139 |
->action( 'relation', __NAMESPACE__ . '\relation_action' ) |
| 140 |
->action( 'footprint', __NAMESPACE__ . '\footprint_action' ) |
| 141 |
->action( 'sub-open-post', __NAMESPACE__ . '\sub_open_post_action' ) |
| 142 |
// List controls: the bound values already arrived with the state; |
| 143 |
// these only reposition the query window. |
| 144 |
->action( |
| 145 |
'search', |
| 146 |
static function ( State $state ) { |
| 147 |
$state->set( 'page', 1 )->set( 'item', 0 )->reset( 'selected' ); |
| 148 |
} |
| 149 |
) |
| 150 |
->action( |
| 151 |
'more', |
| 152 |
static function ( State $state ) { |
| 153 |
$state->set( 'page', (int) $state->get( 'page' ) + 1 ); |
| 154 |
} |
| 155 |
) |
| 156 |
->action( |
| 157 |
'sort', |
| 158 |
static function ( State $state ) { |
| 159 |
$state->set( 'page', 1 )->reset( 'selected' ); |
| 160 |
} |
| 161 |
) |
| 162 |
// The list view: the mode switch and the column chooser, both |
| 163 |
// remembered per user — parts/actions.php. |
| 164 |
->action( 'view', __NAMESPACE__ . '\view_action' ) |
| 165 |
->action( 'set-columns', __NAMESPACE__ . '\set_columns_action' ) |
| 166 |
// Content mutations — parts/actions.php. |
| 167 |
->action( 'edit', __NAMESPACE__ . '\edit_action' ) |
| 168 |
->action( 'add-user', __NAMESPACE__ . '\add_user_action' ) |
| 169 |
->action( 'trash', __NAMESPACE__ . '\trash_action' ) |
| 170 |
->action( 'sub-open', __NAMESPACE__ . '\sub_open_action' ) |
| 171 |
->action( 'quick-edit', __NAMESPACE__ . '\quick_edit_action' ) |
| 172 |
->action( 'bulk-trash', __NAMESPACE__ . '\bulk_trash_action' ) |
| 173 |
// The Agents section — parts/agents.php. |
| 174 |
->action( 'agent-draft', __NAMESPACE__ . '\agent_draft_action' ) |
| 175 |
->action( 'agent-create', __NAMESPACE__ . '\agent_create_action' ) |
| 176 |
->action( 'agent-update', __NAMESPACE__ . '\agent_update_action' ) |
| 177 |
->action( 'agent-delete', __NAMESPACE__ . '\agent_delete_action' ) |
| 178 |
// The data payload — parts/payload.php. |
| 179 |
->data( __NAMESPACE__ . '\payload' ); |
| 180 |
|