exist with that id.' ), array( 'status' => 404 ) ); $id = (int) $id; if ( $id <= 0 ) { return $error; } $post = get_post( $id ); if ( empty( $post ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) { return $error; } return $post; } /** * Checks if a given request has access to read a single global style. * * @since 5.9.0 * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has read access, WP_Error object otherwise. */ public function get_item_permissions_check( $request ) { $post = $this->get_post( $request['id'] ); if ( is_wp_error( $post ) ) { return $post; } if ( 'edit' === $request['context'] && $post && ! $this->check_update_permission( $post ) ) { return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit this global style.' ), array( 'status' => rest_authorization_required_code() ) ); } if ( ! $this->check_read_permission( $post ) ) { return new WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to view this global style.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Checks if a global style can be read. * * @since 5.9.0 * * @param WP_Post $post Post object. * @return bool Whether the post can be read. */ public function check_read_permission( $post ) { return current_user_can( 'read_post', $post->ID ); } /** * Checks if a given request has access to write a single global styles config. * * @since 5.9.0 * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has write access for the item, WP_Error object otherwise. */ public function update_item_permissions_check( $request ) { $post = $this->get_post( $request['id'] ); if ( is_wp_error( $post ) ) { return $post; } if ( $post && ! $this->check_update_permission( $post ) ) { return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this global style.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Prepares a single global styles config for update. * * @since 5.9.0 * @since 6.2.0 Added validation of styles.css property. * @since 6.6.0 Added registration of block style variations from theme.json sources (theme.json, user theme.json, partials). * * @param WP_REST_Request $request Request object. * @return stdClass|WP_Error Prepared item on success. WP_Error on when the custom CSS is not valid. */ protected function prepare_item_for_database( $request ) { $changes = new stdClass(); $changes->ID = $request['id']; $post = get_post( $request['id'] ); $existing_config = array(); if ( $post ) { $existing_config = json_decode( $post->post_content, true ); $json_decoding_error = json_last_error(); if ( JSON_ERROR_NONE !== $json_decoding_error || ! isset( $existing_config['isGlobalStylesUserThemeJSON'] ) || ! $existing_config['isGlobalStylesUserThemeJSON'] ) { $existing_config = array(); } } if ( isset( $request['styles'] ) || isset( $request['settings'] ) ) { $config = array(); if ( isset( $request['styles'] ) ) { if ( isset( $request['styles']['css'] ) ) { $css_validation_result = $this->validate_custom_css( $request['styles']['css'] ); if ( is_wp_error( $css_validation_result ) ) { return $css_validation_result; } } $config['styles'] = $request['styles']; } elseif ( isset( $existing_config['styles'] ) ) { $config['styles'] = $existing_config['styles']; } // Register theme-defined variations e.g. from block style variation partials under `/styles`. $variations = WP_Theme_JSON_Resolver::get_style_variations( 'block' ); wp_register_block_style_variations_from_theme_json_partials( $variations ); if ( isset( $request['settings'] ) ) { $config['settings'] = $request['settings']; } elseif ( isset( $existing_config['settings'] ) ) { $config['settings'] = $existing_config['settings']; } $config['isGlobalStylesUserThemeJSON'] = true; $config['version'] = WP_Theme_JSON::LATEST_SCHEMA; $changes->post_content = wp_json_encode( $config ); } // Post title. if ( isset( $request['title'] ) ) { if ( is_string( $request['title'] ) ) { $changes->post_title = $request['title']; } elseif ( ! empty( $request['title']['raw'] ) ) { $changes->post_title = $request['title']['raw']; } } return $changes; } /** * Prepare a global styles config output for response. * * @since 5.9.0 * @since 6.6.0 Added custom relative theme file URIs to `_links`. * * @param WP_Post $post Global Styles post object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ public function prepare_item_for_response( $post, $request ) { $raw_config = json_decode( $post->post_content, true ); $is_global_styles_user_theme_json = isset( $raw_config['isGlobalStylesUserThemeJSON'] ) && true === $raw_config['isGlobalStylesUserThemeJSON']; $config = array(); $theme_json = null; if ( $is_global_styles_user_theme_json ) { $theme_json = new WP_Theme_JSON( $raw_config, 'custom' ); $config = $theme_json->get_raw_data(); } // Base fields for every post. $fields = $this->get_fields_for_response( $request ); $data = array(); if ( rest_is_field_included( 'id', $fields ) ) { $data['id'] = $post->ID; } if ( rest_is_field_included( 'title', $fields ) ) { $data['title'] = array(); } if ( rest_is_field_included( 'title.raw', $fields ) ) { $data['title']['raw'] = $post->post_title; } if ( rest_is_field_included( 'title.rendered', $fields ) ) { add_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); add_filter( 'private_title_format', array( $this, 'protected_title_format' ) ); $data['title']['rendered'] = get_the_title( $post->ID ); remove_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); remove_filter( 'private_title_format', array( $this, 'protected_title_format' ) ); } if ( rest_is_field_included( 'settings', $fields ) ) { $data['settings'] = ! empty( $config['settings'] ) && $is_global_styles_user_theme_json ? $config['settings'] : new stdClass(); } if ( rest_is_field_included( 'styles', $fields ) ) { $data['styles'] = ! empty( $config['styles'] ) && $is_global_styles_user_theme_json ? $config['styles'] : new stdClass(); } $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; $data = $this->add_additional_fields_to_object( $data, $request ); $data = $this->filter_response_by_context( $data, $context ); // Wrap the data in a response object. $response = rest_ensure_response( $data ); if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { $links = $this->prepare_links( $post->ID ); // Only return resolved URIs for get requests to user theme JSON. if ( $theme_json ) { $resolved_theme_uris = WP_Theme_JSON_Resolver::get_resolved_theme_uris( $theme_json ); if ( ! empty( $resolved_theme_uris ) ) { $links['https://api.w.org/theme-file'] = $resolved_theme_uris; } } $response->add_links( $links ); if ( ! empty( $links['self']['href'] ) ) { $actions = $this->get_available_actions( $post, $request ); $self = $links['self']['href']; foreach ( $actions as $rel ) { $response->add_link( $rel, $self ); } } } return $response; } /** * Prepares links for the request. * * @since 5.9.0 * @since 6.3.0 Adds revisions count and rest URL href to version-history. * * @param integer $id ID. * @return array Links for the given post. */ protected function prepare_links( $id ) { $base = sprintf( '%s/%s', $this->namespace, $this->rest_base ); $links = array( 'self' => array( 'href' => rest_url( trailingslashit( $base ) . $id ), ), 'about' => array( 'href' => rest_url( 'wp/v2/types/' . $this->post_type ), ), ); if ( post_type_supports( $this->post_type, 'revisions' ) ) { $revisions = wp_get_latest_revision_id_and_total_count( $id ); $revisions_count = ! is_wp_error( $revisions ) ? $revisions['count'] : 0; $revisions_base = sprintf( '/%s/%d/revisions', $base, $id ); $links['version-history'] = array( 'href' => rest_url( $revisions_base ), 'count' => $revisions_count, ); } return $links; } /** * Get the link relations available for the post and current user. * * @since 5.9.0 * @since 6.2.0 Added 'edit-css' action. * @since 6.6.0 Added $post and $request parameters. * * @param WP_Post $post Post object. * @param WP_REST_Request $request Request object. * @return array List of link relations. */ protected function get_available_actions( $post, $request ) { $rels = array(); $post_type = get_post_type_object( $post->post_type ); if ( current_user_can( $post_type->cap->publish_posts ) ) { $rels[] = 'https://api.w.org/action-publish'; } if ( current_user_can( 'edit_css' ) ) { $rels[] = 'https://api.w.org/action-edit-css'; } return $rels; } /** * Retrieves the query params for the global styles collection. * * @since 5.9.0 * * @return array Collection parameters. */ public function get_collection_params() { return array(); } /** * Retrieves the global styles type' schema, conforming to JSON Schema. * * @since 5.9.0 * * @return array Item schema data. */ public function get_item_schema() { if ( $this->schema ) { return $this->add_additional_fields_schema( $this->schema ); } $schema = array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => $this->post_type, 'type' => 'object', 'properties' => array( 'id' => array( 'description' => __( 'ID of global styles config.' ), 'type' => 'string', 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), 'styles' => array( 'description' => __( 'Global styles.' ), 'type' => array( 'object' ), 'context' => array( 'view', 'edit' ), ), 'settings' => array( 'description' => __( 'Global settings.' ), 'type' => array( 'object' ), 'context' => array( 'view', 'edit' ), ), 'title' => array( 'description' => __( 'Title of the global styles variation.' ), 'type' => array( 'object', 'string' ), 'default' => '', 'context' => array( 'embed', 'view', 'edit' ), 'properties' => array( 'raw' => array( 'description' => __( 'Title for the global styles variation, as it exists in the database.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), ), 'rendered' => array( 'description' => __( 'HTML title for the post, transformed for display.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), ), ), ), ); $this->schema = $schema; return $this->add_additional_fields_schema( $this->schema ); } /** * Checks if a given request has access to read a single theme global styles config. * * @since 5.9.0 * @since 6.7.0 Allow users with edit post capabilities to view theme global styles. * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. */ public function get_theme_item_permissions_check( $request ) { /* * Verify if the current user has edit_posts capability. * This capability is required to view global styles. */ if ( current_user_can( 'edit_posts' ) ) { return true; } foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { if ( current_user_can( $post_type->cap->edit_posts ) ) { return true; } } /* * Verify if the current user has edit_theme_options capability. */ if ( current_user_can( 'edit_theme_options' ) ) { return true; } return new WP_Error( 'rest_cannot_read_global_styles', __( 'Sorry, you are not allowed to access the global styles on this site.' ), array( 'status' => rest_authorization_required_code(), ) ); } /** * Returns the given theme global styles config. * * @since 5.9.0 * @since 6.6.0 Added custom relative theme file URIs to `_links`. * * @param WP_REST_Request $request The request instance. * @return WP_REST_Response|WP_Error */ public function get_theme_item( $request ) { if ( get_stylesheet() !== $request['stylesheet'] ) { // This endpoint only supports the active theme for now. return new WP_Error( 'rest_theme_not_found', __( 'Theme not found.' ), array( 'status' => 404 ) ); } $theme = WP_Theme_JSON_Resolver::get_merged_data( 'theme' ); $fields = $this->get_fields_for_response( $request ); $data = array(); if ( rest_is_field_included( 'settings', $fields ) ) { $data['settings'] = $theme->get_settings(); } if ( rest_is_field_included( 'styles', $fields ) ) { $raw_data = $theme->get_raw_data(); $data['styles'] = isset( $raw_data['styles'] ) ? $raw_data['styles'] : array(); } $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; $data = $this->add_additional_fields_to_object( $data, $request ); $data = $this->filter_response_by_context( $data, $context ); $response = rest_ensure_response( $data ); if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { $links = array( 'self' => array( 'href' => rest_url( sprintf( '%s/%s/themes/%s', $this->namespace, $this->rest_base, $request['stylesheet'] ) ), ), ); $resolved_theme_uris = WP_Theme_JSON_Resolver::get_resolved_theme_uris( $theme ); if ( ! empty( $resolved_theme_uris ) ) { $links['https://api.w.org/theme-file'] = $resolved_theme_uris; } $response->add_links( $links ); } return $response; } /** * Checks if a given request has access to read a single theme global styles config. * * @since 6.0.0 * @since 6.7.0 Allow users with edit post capabilities to view theme global styles. * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. */ public function get_theme_items_permissions_check( $request ) { return $this->get_theme_item_permissions_check( $request ); } /** * Returns the given theme global styles variations. * * @since 6.0.0 * @since 6.2.0 Returns parent theme variations, if they exist. * @since 6.6.0 Added custom relative theme file URIs to `_links` for each item. * * @param WP_REST_Request $request The request instance. * * @return WP_REST_Response|WP_Error */ public function get_theme_items( $request ) { if ( get_stylesheet() !== $request['stylesheet'] ) { // This endpoint only supports the active theme for now. return new WP_Error( 'rest_theme_not_found', __( 'Theme not found.' ), array( 'status' => 404 ) ); } $response = array(); // Register theme-defined variations e.g. from block style variation partials under `/styles`. $partials = WP_Theme_JSON_Resolver::get_style_variations( 'block' ); wp_register_block_style_variations_from_theme_json_partials( $partials ); $variations = WP_Theme_JSON_Resolver::get_style_variations(); foreach ( $variations as $variation ) { $variation_theme_json = new WP_Theme_JSON( $variation ); $resolved_theme_uris = WP_Theme_JSON_Resolver::get_resolved_theme_uris( $variation_theme_json ); $data = rest_ensure_response( $variation ); if ( ! empty( $resolved_theme_uris ) ) { $data->add_links( array( 'https://api.w.org/theme-file' => $resolved_theme_uris, ) ); } $response[] = $this->prepare_response_for_collection( $data ); } return rest_ensure_response( $response ); } /** * Validate style.css as valid CSS. * * Currently just checks for invalid markup. * * @since 6.2.0 * @since 6.4.0 Changed method visibility to protected. * * @param string $css CSS to validate. * @return true|WP_Error True if the input was validated, otherwise WP_Error. */ protected function validate_custom_css( $css ) { if ( preg_match( '# 400 ) ); } return true; } } _included( '_embedded', $fields ) ) { $response->add_links( $this->prepare_links( $term ) ); } /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php */ return apply_filters( "rest_prepare_{$this->taxonomy}", $response, $term, $request ); } /** * Prepares links for the request. * * @since 5.9.0 * * @param WP_Term $term Term object. * @return array Links for the given term. */ protected function prepare_links( $term ) { $links = parent::prepare_links( $term ); $locations = $this->get_menu_locations( $term->term_id ); foreach ( $locations as $location ) { $url = rest_url( sprintf( 'wp/v2/menu-locations/%s', $location ) ); $links['https://api.w.org/menu-location'][] = array( 'href' => $url, 'embeddable' => true, ); } return $links; } /** * Prepares a single term for create or update. * * @since 5.9.0 * * @param WP_REST_Request $request Request object. * @return object Prepared term data. */ public function prepare_item_for_database( $request ) { $prepared_term = parent::prepare_item_for_database( $request ); $schema = $this->get_item_schema(); if ( isset( $request['name'] ) && ! empty( $schema['properties']['name'] ) ) { $prepared_term->{'menu-name'} = $request['name']; } return $prepared_term; } /** * Creates a single term in a taxonomy. * * @since 5.9.0 * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function create_item( $request ) { if ( isset( $request['parent'] ) ) { if ( ! is_taxonomy_hierarchical( $this->taxonomy ) ) { return new WP_Error( 'rest_taxonomy_not_hierarchical', __( 'Cannot set parent term, taxonomy is not hierarchical.' ), array( 'status' => 400 ) ); } $parent = wp_get_nav_menu_object( (int) $request['parent'] ); if ( ! $parent ) { return new WP_Error( 'rest_term_invalid', __( 'Parent term does not exist.' ), array( 'status' => 400 ) ); } } $prepared_term = $this->prepare_item_for_database( $request ); $term = wp_update_nav_menu_object( 0, wp_slash( (array) $prepared_term ) ); if ( is_wp_error( $term ) ) { /* * If we're going to inform the client that the term already exists, * give them the identifier for future use. */ if ( in_array( 'menu_exists', $term->get_error_codes(), true ) ) { $existing_term = get_term_by( 'name', $prepared_term->{'menu-name'}, $this->taxonomy ); $term->add_data( $existing_term->term_id, 'menu_exists' ); $term->add_data( array( 'status' => 400, 'term_id' => $existing_term->term_id, ) ); } else { $term->add_data( array( 'status' => 400 ) ); } return $term; } $term = $this->get_term( $term ); /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php */ do_action( "rest_insert_{$this->taxonomy}", $term, $request, true ); $schema = $this->get_item_schema(); if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) { $meta_update = $this->meta->update_value( $request['meta'], $term->term_id ); if ( is_wp_error( $meta_update ) ) { return $meta_update; } } $locations_update = $this->handle_locations( $term->term_id, $request ); if ( is_wp_error( $locations_update ) ) { return $locations_update; } $this->handle_auto_add( $term->term_id, $request ); $fields_update = $this->update_additional_fields_for_object( $term, $request ); if ( is_wp_error( $fields_update ) ) { return $fields_update; } $request->set_param( 'context', 'view' ); /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php */ do_action( "rest_after_insert_{$this->taxonomy}", $term, $request, true ); $response = $this->prepare_item_for_response( $term, $request ); $response = rest_ensure_response( $response ); $response->set_status( 201 ); $response->header( 'Location', rest_url( $this->namespace . '/' . $this->rest_base . '/' . $term->term_id ) ); return $response; } /** * Updates a single term from a taxonomy. * * @since 5.9.0 * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function update_item( $request ) { $term = $this->get_term( $request['id'] ); if ( is_wp_error( $term ) ) { return $term; } if ( isset( $request['parent'] ) ) { if ( ! is_taxonomy_hierarchical( $this->taxonomy ) ) { return new WP_Error( 'rest_taxonomy_not_hierarchical', __( 'Cannot set parent term, taxonomy is not hierarchical.' ), array( 'status' => 400 ) ); } $parent = get_term( (int) $request['parent'], $this->taxonomy ); if ( ! $parent ) { return new WP_Error( 'rest_term_invalid', __( 'Parent term does not exist.' ), array( 'status' => 400 ) ); } } $prepared_term = $this->prepare_item_for_database( $request ); // Only update the term if we have something to update. if ( ! empty( $prepared_term ) ) { if ( ! isset( $prepared_term->{'menu-name'} ) ) { // wp_update_nav_menu_object() requires that the menu-name is always passed. $prepared_term->{'menu-name'} = $term->name; } $update = wp_update_nav_menu_object( $term->term_id, wp_slash( (array) $prepared_term ) ); if ( is_wp_error( $update ) ) { return $update; } } $term = get_term( $term->term_id, $this->taxonomy ); /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php */ do_action( "rest_insert_{$this->taxonomy}", $term, $request, false ); $schema = $this->get_item_schema(); if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) { $meta_update = $this->meta->update_value( $request['meta'], $term->term_id ); if ( is_wp_error( $meta_update ) ) { return $meta_update; } } $locations_update = $this->handle_locations( $term->term_id, $request ); if ( is_wp_error( $locations_update ) ) { return $locations_update; } $this->handle_auto_add( $term->term_id, $request ); $fields_update = $this->update_additional_fields_for_object( $term, $request ); if ( is_wp_error( $fields_update ) ) { return $fields_update; } $request->set_param( 'context', 'view' ); /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php */ do_action( "rest_after_insert_{$this->taxonomy}", $term, $request, false ); $response = $this->prepare_item_for_response( $term, $request ); return rest_ensure_response( $response ); } /** * Deletes a single term from a taxonomy. * * @since 5.9.0 * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function delete_item( $request ) { $term = $this->get_term( $request['id'] ); if ( is_wp_error( $term ) ) { return $term; } // We don't support trashing for terms. if ( ! $request['force'] ) { /* translators: %s: force=true */ return new WP_Error( 'rest_trash_not_supported', sprintf( __( "Menus do not support trashing. Set '%s' to delete." ), 'force=true' ), array( 'status' => 501 ) ); } $request->set_param( 'context', 'view' ); $previous = $this->prepare_item_for_response( $term, $request ); $result = wp_delete_nav_menu( $term ); if ( ! $result || is_wp_error( $result ) ) { return new WP_Error( 'rest_cannot_delete', __( 'The menu cannot be deleted.' ), array( 'status' => 500 ) ); } $response = new WP_REST_Response(); $response->set_data( array( 'deleted' => true, 'previous' => $previous->get_data(), ) ); /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php */ do_action( "rest_delete_{$this->taxonomy}", $term, $response, $request ); return $response; } /** * Returns the value of a menu's auto_add setting. * * @since 5.9.0 * * @param int $menu_id The menu id to query. * @return bool The value of auto_add. */ protected function get_menu_auto_add( $menu_id ) { $nav_menu_option = (array) get_option( 'nav_menu_options', array( 'auto_add' => array() ) ); return in_array( $menu_id, $nav_menu_option['auto_add'], true ); } /** * Updates the menu's auto add from a REST request. * * @since 5.9.0 * * @param int $menu_id The menu id to update. * @param WP_REST_Request $request Full details about the request. * @return bool True if the auto add setting was successfully updated. */ protected function handle_auto_add( $menu_id, $request ) { if ( ! isset( $request['auto_add'] ) ) { return true; } $nav_menu_option = (array) get_option( 'nav_menu_options', array( 'auto_add' => array() ) ); if ( ! isset( $nav_menu_option['auto_add'] ) ) { $nav_menu_option['auto_add'] = array(); } $auto_add = $request['auto_add']; $i = array_search( $menu_id, $nav_menu_option['auto_add'], true ); if ( $auto_add && false === $i ) { $nav_menu_option['auto_add'][] = $menu_id; } elseif ( ! $auto_add && false !== $i ) { array_splice( $nav_menu_option['auto_add'], $i, 1 ); } $update = update_option( 'nav_menu_options', $nav_menu_option ); /** This action is documented in wp-includes/nav-menu.php */ do_action( 'wp_update_nav_menu', $menu_id ); return $update; } /** * Returns the names of the locations assigned to the menu. * * @since 5.9.0 * * @param int $menu_id The menu id. * @return string[] The locations assigned to the menu. */ protected function get_menu_locations( $menu_id ) { $locations = get_nav_menu_locations(); $menu_locations = array(); foreach ( $locations as $location => $assigned_menu_id ) { if ( $menu_id === $assigned_menu_id ) { $menu_locations[] = $location; } } return $menu_locations; } /** * Updates the menu's locations from a REST request. * * @since 5.9.0 * * @param int $menu_id The menu id to update. * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True on success, a WP_Error on an error updating any of the locations. */ protected function handle_locations( $menu_id, $request ) { if ( ! isset( $request['locations'] ) ) { return true; } $menu_locations = get_registered_nav_menus(); $menu_locations = array_keys( $menu_locations ); $new_locations = array(); foreach ( $request['locations'] as $location ) { if ( ! in_array( $location, $menu_locations, true ) ) { return new WP_Error( 'rest_invalid_menu_location', __( 'Invalid menu location.' ), array( 'status' => 400, 'location' => $location, ) ); } $new_locations[ $location ] = $menu_id; } $assigned_menu = get_nav_menu_locations(); foreach ( $assigned_menu as $location => $term_id ) { if ( $term_id === $menu_id ) { unset( $assigned_menu[ $location ] ); } } $new_assignments = array_merge( $assigned_menu, $new_locations ); set_theme_mod( 'nav_menu_locations', $new_assignments ); return true; } /** * Retrieves the term's schema, conforming to JSON Schema. * * @since 5.9.0 * * @return array Item schema data. */ public function get_item_schema() { if ( $this->schema ) { return $this->add_additional_fields_schema( $this->schema ); } $schema = parent::get_item_schema(); unset( $schema['properties']['count'], $schema['properties']['link'], $schema['properties']['taxonomy'] ); $schema['properties']['locations'] = array( 'description' => __( 'The locations assigned to the menu.' ), 'type' => 'array', 'items' => array( 'type' => 'string', ), 'context' => array( 'view', 'edit' ), 'arg_options' => array( 'validate_callback' => static function ( $locations, $request, $param ) { $valid = rest_validate_request_arg( $locations, $request, $param ); if ( true !== $valid ) { return $valid; } $locations = rest_sanitize_request_arg( $locations, $request, $param ); foreach ( $locations as $location ) { if ( ! array_key_exists( $location, get_registered_nav_menus() ) ) { return new WP_Error( 'rest_invalid_menu_location', __( 'Invalid menu location.' ), array( 'location' => $location, ) ); } } return true; }, ), ); $schema['properties']['auto_add'] = array( 'description' => __( 'Whether to automatically add top level pages to this menu.' ), 'context' => array( 'view', 'edit' ), 'type' => 'boolean', ); $this->schema = $schema; return $this->add_additional_fields_schema( $this->schema ); } } {"id":1533,"date":"2024-03-23T22:15:42","date_gmt":"2024-03-23T21:15:42","guid":{"rendered":"http:\/\/nasopresse.com\/?p=1533"},"modified":"2024-03-23T22:15:42","modified_gmt":"2024-03-23T21:15:42","slug":"cote-divoire-economie-le-commerce-equitable-connait-une-bonne-dynamique-en-cote-divoire-maizan-paul","status":"publish","type":"post","link":"https:\/\/nasopresse.com\/2024\/03\/23\/cote-divoire-economie-le-commerce-equitable-connait-une-bonne-dynamique-en-cote-divoire-maizan-paul\/","title":{"rendered":"C\u00f4te d\u2019Ivoire \/ Economie \/ Le commerce \u00e9quitable connait une bonne dynamique en C\u00f4te d’Ivoire (Maizan Paul)"},"content":{"rendered":"

\u2018\u2019Le commerce \u00e9quitable connait un d\u00e9veloppement rapide en Afrique de l’ouest et particuli\u00e8rement en C\u00f4te d’Ivoire. Il connait une bonne dynamique de croissance\u2019\u2019, a affirm\u00e9 vendredi 22 mars 2024 \u00e0 Abidjan le Secr\u00e9taire g\u00e9n\u00e9ral du R\u00e9seau ivoirien du commerce \u00e9quitable (RICE) M. Maizan Kobena Paul.<\/p>\n

\"\"<\/p>\n

Maizan a fait cette d\u00e9claration \u00e0 l\u2019occasion de la 3e \u00e9dition de la Journ\u00e9e nationale du commerce \u00e9quitable (JNCE) qui a eu lieu du 22 au 23 mars 2024 \u00e0 l\u2019auditorium de la CAISTAB au Plateau (Centre abidjanais des affaires). Une \u00e9dition plac\u00e9e sous le patronage du ministre d\u2019Etat ivoirien, ministre de l\u2019Agriculture, du d\u00e9veloppement rural et des productions vivri\u00e8res, Kobena Kouassi Adjoumani.<\/p>\n

\u2018\u2019Le commerce \u00e9quitable connait un d\u00e9veloppement rapide en Afrique de l’ouest et particuli\u00e8rement en C\u00f4te d’Ivoire. D’une seule organisation en 2004, on d\u00e9nombre \u00e0 ce jour 265 organisations certifi\u00e9es commerce \u00e9quitable. Les volumes de cacao vendu aux conditions commerce \u00e9quitable, sont pass\u00e9 de 25 tonnes en 2004 \u00e0 156 000 tonnes \u00e0 ce jour\u2019\u2019, a d\u00e9clar\u00e9 le SG.<\/p>\n

Selon lui, Les autres fili\u00e8res certifi\u00e9es commerce \u00e9quitable notamment l’anacarde, la banane, la noix de coco, la mangue, le miel, l’artisanat connaissent aussi une bonne dynamique de croissance.<\/p>\n

Le RICE est l’association des organisations de producteurs certifi\u00e9s commerce \u00e9quitable en C\u00f4te d’Ivoire. Il a vu le jour en juillet 2009 \u00e0 l’initiative de 9 coop\u00e9ratives. Il vise \u00e0 favoriser les \u00e9changes commerciaux \u00e9quitables profitant \u00e0 toutes les parties prenantes notamment les producteurs et les travailleurs.<\/p>\n

\"\"<\/p>\n

Le commerce \u00e9quitable permet \u00e9galement de garantie un revenu stable et une prime qui donne la possibilit\u00e9 aux producteurs d’investir dans d\u2019autres projets, de pr\u00e9server l’environnement en encourageant \u00e0 de meilleures pratiques environnementale, \u00e0 l’application de m\u00e9thodes responsables de production, a expliqu\u00e9 M. Maizan Paul.<\/p>\n

Durant ces deux jours, il s\u2019est agi de sensibiliser les acteurs de toute la cha\u00eene de valeur sur la contribution du commerce \u00e9quitable, d\u2019\u00e9tudier les voies d’am\u00e9lioration de fonctionnement du commerce \u00e9quitable pour une plus grande efficacit\u00e9 au service des producteurs autour des panels, des tables rondes, atelier d’\u00e9changes et espace des expositions ventes.<\/p>\n

\"\"<\/p>\n

Bernard Kouassi du minist\u00e8re de l\u2019Agriculture, du d\u00e9veloppement rural et des productions vivri\u00e8res, repr\u00e9sentant le ministre Kobena Kouassi Adjoumani, a exprim\u00e9 toute sa satisfaction de pr\u00e9sider ces journ\u00e9es du RICE.<\/p>\n

DNG<\/strong><\/p>\n

 <\/p>\n","protected":false},"excerpt":{"rendered":"

C\u00f4te d\u2019Ivoire \/ Economie \/ Le commerce \u00e9quitable connait une bonne dynamique en C\u00f4te d’Ivoire (Maizan Paul)<\/p>\n","protected":false},"author":1,"featured_media":1534,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-1533","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-np-economie"],"acf":[],"_links":{"self":[{"href":"https:\/\/nasopresse.com\/wp-json\/wp\/v2\/posts\/1533","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nasopresse.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nasopresse.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nasopresse.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nasopresse.com\/wp-json\/wp\/v2\/comments?post=1533"}],"version-history":[{"count":1,"href":"https:\/\/nasopresse.com\/wp-json\/wp\/v2\/posts\/1533\/revisions"}],"predecessor-version":[{"id":1537,"href":"https:\/\/nasopresse.com\/wp-json\/wp\/v2\/posts\/1533\/revisions\/1537"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nasopresse.com\/wp-json\/wp\/v2\/media\/1534"}],"wp:attachment":[{"href":"https:\/\/nasopresse.com\/wp-json\/wp\/v2\/media?parent=1533"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nasopresse.com\/wp-json\/wp\/v2\/categories?post=1533"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nasopresse.com\/wp-json\/wp\/v2\/tags?post=1533"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}