class-avcf-abilities-bricks-pro.php
4 weeks ago
class-avcf-abilities-bricks.php
4 weeks ago
class-avcf-bricks-detector.php
4 weeks ago
class-avcf-bricks-helpers.php
4 weeks ago
class-avcf-abilities-bricks.php
343 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Bricks — MCP abilities (core: content tree + page settings). |
| 4 | * |
| 5 | * The stable, load-bearing surface: read/edit the flat element array Bricks |
| 6 | * stores per area (content/header/footer), list element types, and read/write |
| 7 | * page settings. The deeper Bricks surfaces (global classes, components, theme |
| 8 | * styles, variables, interactions, dynamic data, templates) are a separate |
| 9 | * advanced pass — they are site-wide / internal-heavy, like Elementor Pro's |
| 10 | * advanced set. |
| 11 | * |
| 12 | * Built on the documented Bricks storage model (read from the Novamira |
| 13 | * reference); NOT runtime-tested here. Bricks' own validation engine and |
| 14 | * code-element signing are not reproduced — code elements are written UNSIGNED |
| 15 | * (Bricks won't execute unsigned code; signing is the excluded execute-PHP |
| 16 | * risk class). |
| 17 | * |
| 18 | * @package atarim-visual-collaboration |
| 19 | */ |
| 20 | |
| 21 | if ( ! defined('ABSPATH') ) { |
| 22 | exit; |
| 23 | } |
| 24 | |
| 25 | class AVCF_Abilities_Bricks extends AVCF_Abilities_Base { |
| 26 | |
| 27 | /** @var AVCF_Bricks_Detector */ |
| 28 | private $detector; |
| 29 | |
| 30 | public function __construct() { |
| 31 | $this->detector = new AVCF_Bricks_Detector(); |
| 32 | } |
| 33 | |
| 34 | public function register() { |
| 35 | if ( ! $this->detector->avcf_bricks_is_available() ) { |
| 36 | return; |
| 37 | } |
| 38 | $this->register_check_setup(); |
| 39 | $this->register_list_elements(); |
| 40 | $this->register_get_content(); |
| 41 | $this->register_set_content(); |
| 42 | $this->register_insert_content(); |
| 43 | $this->register_patch_elements(); |
| 44 | $this->register_remove_content(); |
| 45 | $this->register_settings(); |
| 46 | } |
| 47 | |
| 48 | /* ------------------------------ shared ----------------------------- */ |
| 49 | |
| 50 | private function ro_meta() { |
| 51 | return [ 'mcp' => [ 'public' => true, 'type' => 'tool' ], 'annotations' => [ 'readonly' => true, 'destructive' => false, 'idempotent' => true ] ]; |
| 52 | } |
| 53 | private function write_meta( $destructive = false ) { |
| 54 | return [ 'mcp' => [ 'public' => true, 'type' => 'tool' ], 'annotations' => [ 'readonly' => false, 'destructive' => (bool) $destructive, 'idempotent' => false ] ]; |
| 55 | } |
| 56 | private function std_out() { |
| 57 | return [ 'type' => 'object', 'properties' => [ 'success' => [ 'type' => 'boolean' ], 'message' => [ 'type' => 'string' ] ], 'required' => [ 'success', 'message' ] ]; |
| 58 | } |
| 59 | private function can_edit( $post_id ) { |
| 60 | return current_user_can( 'edit_post', (int) $post_id ) || current_user_can( 'edit_posts' ); |
| 61 | } |
| 62 | private function require_post( $post_id ) { |
| 63 | if ( $post_id <= 0 || ! get_post( $post_id ) ) { return [ 'success' => false, 'message' => 'A valid post_id is required.' ]; } |
| 64 | return null; |
| 65 | } |
| 66 | private function area_prop() { |
| 67 | return [ 'type' => 'string', 'enum' => [ 'content', 'header', 'footer' ], 'default' => 'content', 'description' => 'Which Bricks area to target.' ]; |
| 68 | } |
| 69 | |
| 70 | /* --------------------------- check-setup --------------------------- */ |
| 71 | |
| 72 | private function register_check_setup() { |
| 73 | $d = $this->detector; |
| 74 | wp_register_ability( 'atarim/bricks-check-setup', [ |
| 75 | 'label' => 'Check Bricks Setup', 'category' => 'atarim', |
| 76 | 'description' => 'Call first before other Bricks abilities. Reports whether Bricks is active and its version.', |
| 77 | 'input_schema' => [ 'type' => 'object', 'properties' => [], 'additionalProperties' => false ], |
| 78 | 'output_schema'=> [ 'type' => 'object', 'properties' => [ 'success' => [ 'type' => 'boolean' ], 'active' => [ 'type' => 'boolean' ], 'version' => [ 'type' => 'string' ], 'message' => [ 'type' => 'string' ] ], 'required' => [ 'success', 'active', 'message' ] ], |
| 79 | 'execute_callback' => function( $input = [] ) use ( $d ) { |
| 80 | return [ 'success' => true, 'active' => $d->avcf_bricks_is_available(), 'version' => $d->avcf_bricks_version(), 'message' => 'OK.' ]; |
| 81 | }, |
| 82 | 'permission_callback' => function() { return current_user_can( 'edit_posts' ); }, |
| 83 | 'meta' => $this->ro_meta(), |
| 84 | ] ); |
| 85 | } |
| 86 | |
| 87 | /* --------------------------- list-elements ------------------------- */ |
| 88 | |
| 89 | private function register_list_elements() { |
| 90 | wp_register_ability( 'atarim/bricks-list-elements', [ |
| 91 | 'label' => 'List Bricks Elements', 'category' => 'atarim', |
| 92 | 'description' => 'List the registered Bricks element types (name + label) — the values you pass as "name" when inserting elements (e.g. "section", "container", "heading", "text", "image", "button").', |
| 93 | 'input_schema' => [ 'type' => 'object', 'properties' => [], 'additionalProperties' => false ], |
| 94 | 'output_schema'=> [ 'type' => 'object', 'properties' => [ 'success' => [ 'type' => 'boolean' ], 'elements' => [ 'type' => 'array' ], 'message' => [ 'type' => 'string' ] ], 'required' => [ 'success', 'message' ] ], |
| 95 | 'execute_callback' => function( $input = [] ) { |
| 96 | $types = AVCF_Bricks_Helpers::element_types(); |
| 97 | return [ 'success' => true, 'elements' => $types, 'message' => $types ? sprintf( '%d element type(s).', count( $types ) ) : 'Element registry not available on this build.' ]; |
| 98 | }, |
| 99 | 'permission_callback' => function() { return current_user_can( 'edit_posts' ); }, |
| 100 | 'meta' => $this->ro_meta(), |
| 101 | ] ); |
| 102 | } |
| 103 | |
| 104 | /* --------------------------- get-content --------------------------- */ |
| 105 | |
| 106 | private function register_get_content() { |
| 107 | $self = $this; |
| 108 | wp_register_ability( 'atarim/bricks-get-content', [ |
| 109 | 'label' => 'Get Bricks Content', 'category' => 'atarim', |
| 110 | 'description' => 'Read a post\'s Bricks element structure for an area. Bricks stores a FLAT element list — each node has id, name (type), parent (parent id, 0 = top level), children (child ids), and settings. By default returns a structural summary (no settings); pass element_id for one element\'s full data, or include_settings:true for the whole area with settings.', |
| 111 | 'input_schema' => [ 'type' => 'object', 'properties' => [ |
| 112 | 'post_id' => [ 'type' => 'integer', 'minimum' => 1 ], |
| 113 | 'area' => $self->area_prop(), |
| 114 | 'element_id' => [ 'type' => 'string' ], |
| 115 | 'include_settings' => [ 'type' => 'boolean', 'default' => false ], |
| 116 | ], 'required' => [ 'post_id' ], 'additionalProperties' => false ], |
| 117 | 'output_schema'=> [ 'type' => 'object', 'properties' => [ 'success' => [ 'type' => 'boolean' ], 'elements' => [ 'type' => 'array' ], 'element' => [ 'type' => 'object' ], 'message' => [ 'type' => 'string' ] ], 'required' => [ 'success', 'message' ] ], |
| 118 | 'execute_callback' => function( $input = [] ) use ( $self ) { |
| 119 | $post_id = (int) $input['post_id']; $err = $self->require_post( $post_id ); if ( $err ) { return $err; } |
| 120 | $area = isset( $input['area'] ) ? (string) $input['area'] : 'content'; |
| 121 | $els = AVCF_Bricks_Helpers::read_area( $post_id, $area ); |
| 122 | if ( ! empty( $input['element_id'] ) ) { |
| 123 | $el = AVCF_Bricks_Helpers::find( $els, (string) $input['element_id'] ); |
| 124 | if ( $el === null ) { return [ 'success' => false, 'message' => sprintf( 'Element "%s" not found in %s.', $input['element_id'], $area ) ]; } |
| 125 | return [ 'success' => true, 'element' => $el, 'message' => 'OK.' ]; |
| 126 | } |
| 127 | if ( ! empty( $input['include_settings'] ) ) { |
| 128 | return [ 'success' => true, 'elements' => $els, 'message' => 'OK (full).' ]; |
| 129 | } |
| 130 | return [ 'success' => true, 'elements' => AVCF_Bricks_Helpers::summarize( $els ), 'message' => 'OK (summary).' ]; |
| 131 | }, |
| 132 | 'permission_callback' => function() { return current_user_can( 'edit_posts' ); }, |
| 133 | 'meta' => $this->ro_meta(), |
| 134 | ] ); |
| 135 | } |
| 136 | |
| 137 | /* --------------------------- set-content --------------------------- */ |
| 138 | |
| 139 | private function register_set_content() { |
| 140 | $self = $this; |
| 141 | wp_register_ability( 'atarim/bricks-set-content', [ |
| 142 | 'label' => 'Set Bricks Content', 'category' => 'atarim', |
| 143 | 'description' => 'Replace a post\'s ENTIRE Bricks element list for an area with the supplied flat array (same shape get-content returns with include_settings:true). Full overwrite — for targeted changes prefer insert-content / patch-elements / remove-content. Missing ids/children are filled in. Code elements are stored UNSIGNED and will not execute until signed in the Bricks editor.', |
| 144 | 'input_schema' => [ 'type' => 'object', 'properties' => [ |
| 145 | 'post_id' => [ 'type' => 'integer', 'minimum' => 1 ], |
| 146 | 'area' => $self->area_prop(), |
| 147 | 'elements' => [ 'type' => 'array' ], |
| 148 | ], 'required' => [ 'post_id', 'elements' ], 'additionalProperties' => false ], |
| 149 | 'output_schema'=> $this->std_out(), |
| 150 | 'execute_callback' => function( $input = [] ) use ( $self ) { |
| 151 | $post_id = (int) $input['post_id']; $err = $self->require_post( $post_id ); if ( $err ) { return $err; } |
| 152 | if ( ! $self->can_edit( $post_id ) ) { return [ 'success' => false, 'message' => 'No permission to edit this post.' ]; } |
| 153 | if ( ! isset( $input['elements'] ) || ! is_array( $input['elements'] ) ) { return [ 'success' => false, 'message' => 'elements must be an array.' ]; } |
| 154 | $area = isset( $input['area'] ) ? (string) $input['area'] : 'content'; |
| 155 | if ( ! AVCF_Bricks_Helpers::write_area( $post_id, $area, $input['elements'] ) ) { return [ 'success' => false, 'message' => 'Failed to save (no change or write error).' ]; } |
| 156 | return [ 'success' => true, 'message' => sprintf( 'Replaced Bricks %s on post %d.', $area, $post_id ) ]; |
| 157 | }, |
| 158 | 'permission_callback' => function() { return current_user_can( 'edit_posts' ); }, |
| 159 | 'meta' => $this->write_meta( true ), |
| 160 | ] ); |
| 161 | } |
| 162 | |
| 163 | /* -------------------------- insert-content ------------------------- */ |
| 164 | |
| 165 | private function register_insert_content() { |
| 166 | $self = $this; |
| 167 | wp_register_ability( 'atarim/bricks-insert-content', [ |
| 168 | 'label' => 'Insert Bricks Element', 'category' => 'atarim', |
| 169 | 'description' => 'Insert a new element into a post\'s Bricks area. name is the element type (see list-elements). parent_id nests it under an existing element (omit/0 for top level); the parent/children pointers are kept in sync. settings is the element\'s control values. Returns the new element id. Code elements are stored UNSIGNED.', |
| 170 | 'input_schema' => [ 'type' => 'object', 'properties' => [ |
| 171 | 'post_id' => [ 'type' => 'integer', 'minimum' => 1 ], |
| 172 | 'area' => $self->area_prop(), |
| 173 | 'name' => [ 'type' => 'string', 'description' => 'Element type, e.g. "section", "container", "heading".' ], |
| 174 | 'parent_id' => [ 'type' => 'string', 'description' => 'Parent element id. Omit for top level.' ], |
| 175 | 'settings' => [ 'type' => 'object' ], |
| 176 | 'label' => [ 'type' => 'string' ], |
| 177 | ], 'required' => [ 'post_id', 'name' ], 'additionalProperties' => false ], |
| 178 | 'output_schema'=> [ 'type' => 'object', 'properties' => [ 'success' => [ 'type' => 'boolean' ], 'element_id' => [ 'type' => 'string' ], 'message' => [ 'type' => 'string' ] ], 'required' => [ 'success', 'message' ] ], |
| 179 | 'execute_callback' => function( $input = [] ) use ( $self ) { |
| 180 | $post_id = (int) $input['post_id']; $err = $self->require_post( $post_id ); if ( $err ) { return $err; } |
| 181 | if ( ! $self->can_edit( $post_id ) ) { return [ 'success' => false, 'message' => 'No permission to edit this post.' ]; } |
| 182 | $area = isset( $input['area'] ) ? (string) $input['area'] : 'content'; |
| 183 | $node = [ |
| 184 | 'id' => AVCF_Bricks_Helpers::generate_id(), |
| 185 | 'name' => (string) $input['name'], |
| 186 | 'settings' => isset( $input['settings'] ) && is_array( $input['settings'] ) ? $input['settings'] : [], |
| 187 | 'children' => [], |
| 188 | ]; |
| 189 | if ( isset( $input['label'] ) ) { $node['label'] = (string) $input['label']; } |
| 190 | $els = AVCF_Bricks_Helpers::read_area( $post_id, $area ); |
| 191 | list( $els, $ok ) = AVCF_Bricks_Helpers::insert( $els, isset( $input['parent_id'] ) ? (string) $input['parent_id'] : 0, $node ); |
| 192 | if ( ! $ok ) { return [ 'success' => false, 'message' => sprintf( 'parent_id "%s" not found.', isset( $input['parent_id'] ) ? $input['parent_id'] : '' ) ]; } |
| 193 | if ( ! AVCF_Bricks_Helpers::write_area( $post_id, $area, $els ) ) { return [ 'success' => false, 'message' => 'Failed to save.' ]; } |
| 194 | return [ 'success' => true, 'element_id' => $node['id'], 'message' => sprintf( 'Inserted "%s".', $node['name'] ) ]; |
| 195 | }, |
| 196 | 'permission_callback' => function() { return current_user_can( 'edit_posts' ); }, |
| 197 | 'meta' => $this->write_meta( false ), |
| 198 | ] ); |
| 199 | } |
| 200 | |
| 201 | /* -------------------------- patch-elements ------------------------- */ |
| 202 | |
| 203 | private function register_patch_elements() { |
| 204 | $self = $this; |
| 205 | wp_register_ability( 'atarim/bricks-patch-elements', [ |
| 206 | 'label' => 'Patch Bricks Element', 'category' => 'atarim', |
| 207 | 'description' => 'Update one element by id. settings are shallow-merged into the element\'s existing settings (top-level keys you send overwrite; others kept). Optionally change label/name. Read the element first with get-content (element_id).', |
| 208 | 'input_schema' => [ 'type' => 'object', 'properties' => [ |
| 209 | 'post_id' => [ 'type' => 'integer', 'minimum' => 1 ], |
| 210 | 'area' => $self->area_prop(), |
| 211 | 'element_id' => [ 'type' => 'string' ], |
| 212 | 'settings' => [ 'type' => 'object' ], |
| 213 | 'label' => [ 'type' => 'string' ], |
| 214 | 'name' => [ 'type' => 'string' ], |
| 215 | ], 'required' => [ 'post_id', 'element_id' ], 'additionalProperties' => false ], |
| 216 | 'output_schema'=> $this->std_out(), |
| 217 | 'execute_callback' => function( $input = [] ) use ( $self ) { |
| 218 | $post_id = (int) $input['post_id']; $err = $self->require_post( $post_id ); if ( $err ) { return $err; } |
| 219 | if ( ! $self->can_edit( $post_id ) ) { return [ 'success' => false, 'message' => 'No permission to edit this post.' ]; } |
| 220 | $area = isset( $input['area'] ) ? (string) $input['area'] : 'content'; |
| 221 | $patch = []; |
| 222 | foreach ( [ 'settings', 'label', 'name' ] as $k ) { if ( isset( $input[ $k ] ) ) { $patch[ $k ] = $input[ $k ]; } } |
| 223 | if ( empty( $patch ) ) { return [ 'success' => false, 'message' => 'Provide at least one of settings, label, name.' ]; } |
| 224 | $els = AVCF_Bricks_Helpers::read_area( $post_id, $area ); |
| 225 | $found = false; |
| 226 | $els = AVCF_Bricks_Helpers::patch( $els, (string) $input['element_id'], $patch, $found ); |
| 227 | if ( ! $found ) { return [ 'success' => false, 'message' => sprintf( 'Element "%s" not found.', $input['element_id'] ) ]; } |
| 228 | if ( ! AVCF_Bricks_Helpers::write_area( $post_id, $area, $els ) ) { return [ 'success' => false, 'message' => 'Failed to save.' ]; } |
| 229 | return [ 'success' => true, 'message' => sprintf( 'Updated element "%s".', $input['element_id'] ) ]; |
| 230 | }, |
| 231 | 'permission_callback' => function() { return current_user_can( 'edit_posts' ); }, |
| 232 | 'meta' => $this->write_meta( false ), |
| 233 | ] ); |
| 234 | } |
| 235 | |
| 236 | /* -------------------------- remove-content ------------------------- */ |
| 237 | |
| 238 | private function register_remove_content() { |
| 239 | $self = $this; |
| 240 | wp_register_ability( 'atarim/bricks-remove-content', [ |
| 241 | 'label' => 'Remove Bricks Element', 'category' => 'atarim', |
| 242 | 'description' => 'Remove an element (and all its descendants) from a Bricks area by id, detaching it from its parent. Dry run unless confirm:true.', |
| 243 | 'input_schema' => [ 'type' => 'object', 'properties' => [ |
| 244 | 'post_id' => [ 'type' => 'integer', 'minimum' => 1 ], |
| 245 | 'area' => $self->area_prop(), |
| 246 | 'element_id' => [ 'type' => 'string' ], |
| 247 | 'confirm' => [ 'type' => 'boolean', 'default' => false ], |
| 248 | ], 'required' => [ 'post_id', 'element_id' ], 'additionalProperties' => false ], |
| 249 | 'output_schema'=> [ 'type' => 'object', 'properties' => [ 'success' => [ 'type' => 'boolean' ], 'removed' => [ 'type' => 'boolean' ], 'message' => [ 'type' => 'string' ] ], 'required' => [ 'success', 'message' ] ], |
| 250 | 'execute_callback' => function( $input = [] ) use ( $self ) { |
| 251 | $post_id = (int) $input['post_id']; $err = $self->require_post( $post_id ); if ( $err ) { return $err; } |
| 252 | if ( ! $self->can_edit( $post_id ) ) { return [ 'success' => false, 'message' => 'No permission to edit this post.' ]; } |
| 253 | $area = isset( $input['area'] ) ? (string) $input['area'] : 'content'; |
| 254 | $els = AVCF_Bricks_Helpers::read_area( $post_id, $area ); |
| 255 | if ( AVCF_Bricks_Helpers::find( $els, (string) $input['element_id'] ) === null ) { return [ 'success' => false, 'message' => sprintf( 'Element "%s" not found.', $input['element_id'] ) ]; } |
| 256 | if ( empty( $input['confirm'] ) ) { return [ 'success' => true, 'removed' => false, 'message' => sprintf( 'Dry run: would remove "%s" and its descendants. Re-call with confirm:true.', $input['element_id'] ) ]; } |
| 257 | list( $els, $ok ) = AVCF_Bricks_Helpers::remove( $els, (string) $input['element_id'] ); |
| 258 | if ( ! $ok || ! AVCF_Bricks_Helpers::write_area( $post_id, $area, $els ) ) { return [ 'success' => false, 'message' => 'Failed to remove/save.' ]; } |
| 259 | return [ 'success' => true, 'removed' => true, 'message' => sprintf( 'Removed "%s".', $input['element_id'] ) ]; |
| 260 | }, |
| 261 | 'permission_callback' => function() { return current_user_can( 'edit_posts' ); }, |
| 262 | 'meta' => $this->write_meta( true ), |
| 263 | ] ); |
| 264 | } |
| 265 | |
| 266 | /* ------------------------------ settings --------------------------- */ |
| 267 | |
| 268 | private function register_settings() { |
| 269 | $self = $this; $std = $this->std_out(); |
| 270 | |
| 271 | wp_register_ability( 'atarim/bricks-get-settings', [ |
| 272 | 'label' => 'Get Bricks Page Settings', 'category' => 'atarim', |
| 273 | 'description' => 'Read a post\'s Bricks page settings (the _bricks_page_settings meta — page-level options like SEO, layout, code).', |
| 274 | 'input_schema' => [ 'type' => 'object', 'properties' => [ 'post_id' => [ 'type' => 'integer', 'minimum' => 1 ] ], 'required' => [ 'post_id' ], 'additionalProperties' => false ], |
| 275 | 'output_schema'=> [ 'type' => 'object', 'properties' => [ 'success' => [ 'type' => 'boolean' ], 'settings' => [ 'type' => 'object' ], 'message' => [ 'type' => 'string' ] ], 'required' => [ 'success', 'message' ] ], |
| 276 | 'execute_callback' => function( $input = [] ) use ( $self ) { |
| 277 | $post_id = (int) $input['post_id']; $err = $self->require_post( $post_id ); if ( $err ) { return $err; } |
| 278 | $s = get_post_meta( $post_id, '_bricks_page_settings', true ); |
| 279 | return [ 'success' => true, 'settings' => is_array( $s ) ? $s : [], 'message' => 'OK.' ]; |
| 280 | }, |
| 281 | 'permission_callback' => function() { return current_user_can( 'edit_posts' ); }, |
| 282 | 'meta' => $this->ro_meta(), |
| 283 | ] ); |
| 284 | |
| 285 | wp_register_ability( 'atarim/bricks-list-settings', [ |
| 286 | 'label' => 'List Bricks Page Setting Keys', 'category' => 'atarim', |
| 287 | 'description' => 'List the keys present in a post\'s Bricks page settings.', |
| 288 | 'input_schema' => [ 'type' => 'object', 'properties' => [ 'post_id' => [ 'type' => 'integer', 'minimum' => 1 ] ], 'required' => [ 'post_id' ], 'additionalProperties' => false ], |
| 289 | 'output_schema'=> [ 'type' => 'object', 'properties' => [ 'success' => [ 'type' => 'boolean' ], 'keys' => [ 'type' => 'array' ], 'message' => [ 'type' => 'string' ] ], 'required' => [ 'success', 'message' ] ], |
| 290 | 'execute_callback' => function( $input = [] ) use ( $self ) { |
| 291 | $post_id = (int) $input['post_id']; $err = $self->require_post( $post_id ); if ( $err ) { return $err; } |
| 292 | $s = get_post_meta( $post_id, '_bricks_page_settings', true ); |
| 293 | $keys = is_array( $s ) ? array_keys( $s ) : []; |
| 294 | return [ 'success' => true, 'keys' => $keys, 'message' => sprintf( '%d key(s).', count( $keys ) ) ]; |
| 295 | }, |
| 296 | 'permission_callback' => function() { return current_user_can( 'edit_posts' ); }, |
| 297 | 'meta' => $this->ro_meta(), |
| 298 | ] ); |
| 299 | |
| 300 | wp_register_ability( 'atarim/bricks-set-settings', [ |
| 301 | 'label' => 'Set Bricks Page Settings', 'category' => 'atarim', |
| 302 | 'description' => 'Update a post\'s Bricks page settings. settings is shallow-merged into the existing page settings by default; pass replace:true to overwrite the whole object.', |
| 303 | 'input_schema' => [ 'type' => 'object', 'properties' => [ |
| 304 | 'post_id' => [ 'type' => 'integer', 'minimum' => 1 ], |
| 305 | 'settings' => [ 'type' => 'object' ], |
| 306 | 'replace' => [ 'type' => 'boolean', 'default' => false ], |
| 307 | ], 'required' => [ 'post_id', 'settings' ], 'additionalProperties' => false ], |
| 308 | 'output_schema'=> $std, |
| 309 | 'execute_callback' => function( $input = [] ) use ( $self ) { |
| 310 | $post_id = (int) $input['post_id']; $err = $self->require_post( $post_id ); if ( $err ) { return $err; } |
| 311 | if ( ! $self->can_edit( $post_id ) ) { return [ 'success' => false, 'message' => 'No permission to edit this post.' ]; } |
| 312 | if ( ! isset( $input['settings'] ) || ! is_array( $input['settings'] ) ) { return [ 'success' => false, 'message' => 'settings must be an object.' ]; } |
| 313 | $new = $input['settings']; |
| 314 | if ( empty( $input['replace'] ) ) { |
| 315 | $cur = get_post_meta( $post_id, '_bricks_page_settings', true ); |
| 316 | $new = array_merge( is_array( $cur ) ? $cur : [], $new ); |
| 317 | } |
| 318 | update_post_meta( $post_id, '_bricks_page_settings', $new ); |
| 319 | return [ 'success' => true, 'message' => 'Page settings updated.' ]; |
| 320 | }, |
| 321 | 'permission_callback' => function() { return current_user_can( 'edit_posts' ); }, |
| 322 | 'meta' => $this->write_meta( false ), |
| 323 | ] ); |
| 324 | |
| 325 | wp_register_ability( 'atarim/bricks-set-post-types', [ |
| 326 | 'label' => 'Set Bricks Post Types', 'category' => 'atarim', |
| 327 | 'description' => 'SITE-WIDE. Set which post types the Bricks builder is enabled for (writes the postTypes key in Bricks global settings). post_types is the full array of post type slugs to enable.', |
| 328 | 'input_schema' => [ 'type' => 'object', 'properties' => [ 'post_types' => [ 'type' => 'array', 'items' => [ 'type' => 'string' ] ] ], 'required' => [ 'post_types' ], 'additionalProperties' => false ], |
| 329 | 'output_schema'=> $std, |
| 330 | 'execute_callback' => function( $input = [] ) { |
| 331 | $pts = isset( $input['post_types'] ) && is_array( $input['post_types'] ) ? array_values( array_map( 'sanitize_key', $input['post_types'] ) ) : []; |
| 332 | $opt = get_option( 'bricks_global_settings' ); |
| 333 | if ( ! is_array( $opt ) ) { $opt = []; } |
| 334 | $opt['postTypes'] = $pts; |
| 335 | update_option( 'bricks_global_settings', $opt ); |
| 336 | return [ 'success' => true, 'message' => sprintf( 'Bricks enabled for %d post type(s).', count( $pts ) ) ]; |
| 337 | }, |
| 338 | 'permission_callback' => function() { return current_user_can( 'manage_options' ); }, |
| 339 | 'meta' => $this->write_meta( false ), |
| 340 | ] ); |
| 341 | } |
| 342 | } |
| 343 |