] )->build(); } // if the component is not locked, return true if ( ! $lock_data['locked_by'] ) { return Response_Builder::make( [ 'is_current_user_allow_to_edit' => true, 'locked_by' => null, ] )->build(); } } catch ( \Exception $e ) { error_log( 'Components REST API get_lock_status error: ' . $e->getMessage() ); return Error_Builder::make( 'get_lock_status_failed' ) ->set_status( 500 ) ->set_message( __( 'Failed to get lock status', 'elementor' ) ) ->build(); } } private function archive_components( \WP_REST_Request $request ) { if ( ! Components_Access_Controller::can_delete() ) { return $this->get_insufficient_permissions_error( 'delete' ); } $component_ids = $request->get_param( 'componentIds' ); $status = $request->get_param( 'status' ); try { $result = $this->get_repository()->archive( $component_ids, $status ); } catch ( \Exception $e ) { error_log( 'Components REST API archive_components error: ' . $e->getMessage() ); return Error_Builder::make( 'archive_failed' ) ->set_meta( [ 'error' => $e->getMessage() ] ) ->set_status( 500 ) ->set_message( __( 'Failed to archive components', 'elementor' ) ) ->build(); } return Response_Builder::make( $result )->build(); } private function update_components_title( \WP_REST_Request $request ) { if ( ! Components_Access_Controller::can_rename() ) { return $this->get_insufficient_permissions_error( 'rename' ); } $failed_ids = []; $success_ids = []; $components = $request->get_param( 'components' ); $status = $request->get_param( 'status' ); foreach ( $components as $component ) { $is_success = $this->get_repository()->update_title( $component['componentId'], $component['title'], $status ); if ( ! $is_success ) { $failed_ids[] = $component['componentId']; continue; } $success_ids[] = $component['componentId']; } return Response_Builder::make( [ 'failedIds' => $failed_ids, 'successIds' => $success_ids, ] )->build(); } private function create_validate_components( \WP_REST_Request $request ) { if ( ! Components_Access_Controller::can_create() ) { return $this->get_insufficient_permissions_error( 'create' ); } $items = Collection::make( $request->get_param( 'items' ) ); $components = $this->get_repository()->all(); $result = Save_Components_Validator::make( $components )->validate( $items ); if ( ! $result['success'] ) { return Error_Builder::make( 'components_validation_failed' ) ->set_status( 422 ) ->set_message( 'Validation failed: ' . implode( ', ', $result['messages'] ) ) ->build(); } $circular_result = Circular_Dependency_Validator::make()->validate_new_components( $items ); if ( ! $circular_result['success'] ) { return Error_Builder::make( 'circular_dependency_detected' ) ->set_status( 422 ) ->set_message( __( "Can't add this component - components that contain each other can't be nested.", 'elementor' ) ) ->set_meta( [ 'caused_by' => $circular_result['messages'] ] ) ->build(); } $non_atomic_result = Non_Atomic_Widget_Validator::make()->validate_items( $items ); if ( ! $non_atomic_result['success'] ) { return Error_Builder::make( Non_Atomic_Widget_Validator::ERROR_CODE ) ->set_status( 422 ) ->set_message( __( 'Components require atomic elements only. Remove widgets to create this component.', 'elementor' ) ) ->set_meta( [ 'non_atomic_elements' => $non_atomic_result['non_atomic_elements'] ] ) ->build(); } $validation_errors = $items->map_with_keys( function ( $item ) { try { if ( isset( $item['settings'] ) ) { $this->parse_settings( $item['settings'] ); } } catch ( \Exception $e ) { return [ $item['uid'] => $e->getMessage() ]; } return [ $item['uid'] => null ]; } ) ->filter( fn( $value ) => null !== $value ); if ( ! $validation_errors->is_empty() ) { return Error_Builder::make( 'settings_validation_failed' ) ->set_status( 422 ) ->set_message( 'Settings validation failed: ' . json_encode( $validation_errors->all() ) ) ->build(); } return Response_Builder::make() ->set_status( 200 ) ->build(); } private function parse_settings( array $settings ): array { $result = []; if ( empty( $settings ) ) { return $result; } if ( isset( $settings['overridable_props'] ) ) { $parser = Component_Overridable_Props_Parser::make(); $overridable_props_result = $parser->parse( $settings['overridable_props'] ); if ( ! $overridable_props_result->is_valid() ) { throw new \Exception( esc_html( 'Validation failed for overridable_props: ' . $overridable_props_result->errors()->to_string() ) ); } $result['overridable_props'] = $overridable_props_result->unwrap(); } return $result; } private function route_wrapper( callable $cb ) { try { $response = $cb(); } catch ( \Exception $e ) { return Error_Builder::make( 'unexpected_error' ) ->set_message( __( 'Something went wrong', 'elementor' ) ) ->build(); } return $response; } private function get_insufficient_permissions_error( string $action ) { return Error_Builder::make( 'insufficient_permissions' ) ->set_status( 403 ) ->set_message( __( 'You do not have permission to perform this action.', 'elementor' ) ) ->set_meta( [ 'action' => $action, 'tier' => Components_Access_Controller::get_access_tier(), ] ) ->build(); } }