/** * REST API: WP_REST_Terms_Controller class * * @package WordPress * @subpackage REST_API * @since 4.7.0 */ /** * Core class used to managed terms associated with a taxonomy via the REST API. * * @since 4.7.0 * * @see WP_REST_Controller */ class WP_REST_Terms_Controller extends WP_REST_Controller { /** * Taxonomy key. * * @since 4.7.0 * @var string */ protected $taxonomy; /** * Instance of a term meta fields object. * * @since 4.7.0 * @var WP_REST_Term_Meta_Fields */ protected $meta; /** * Column to have the terms be sorted by. * * @since 4.7.0 * @var string */ protected $sort_column; /** * Number of terms that were found. * * @since 4.7.0 * @var int */ protected $total_terms; /** * Constructor. * * @since 4.7.0 * * @param string $taxonomy Taxonomy key. */ public function __construct( $taxonomy ) { $this->taxonomy = $taxonomy; $this->namespace = 'wp/v2'; $tax_obj = get_taxonomy( $taxonomy ); $this->rest_base = ! empty( $tax_obj->rest_base ) ? $tax_obj->rest_base : $tax_obj->name; $this->meta = new WP_REST_Term_Meta_Fields( $taxonomy ); } /** * Registers the routes for the objects of the controller. * * @since 4.7.0 * * @see register_rest_route() */ public function register_routes() { register_rest_route( $this->namespace, '/' . $this->rest_base, array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_items' ), 'permission_callback' => array( $this, 'get_items_permissions_check' ), 'args' => $this->get_collection_params(), ), array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'create_item' ), 'permission_callback' => array( $this, 'create_item_permissions_check' ), 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), ), 'schema' => array( $this, 'get_public_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[\d]+)', array( 'args' => array( 'id' => array( 'description' => __( 'Unique identifier for the term.' ), 'type' => 'integer', ), ), array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_item' ), 'permission_callback' => array( $this, 'get_item_permissions_check' ), 'args' => array( 'context' => $this->get_context_param( array( 'default' => 'view' ) ), ), ), array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'update_item' ), 'permission_callback' => array( $this, 'update_item_permissions_check' ), 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), ), array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => array( $this, 'delete_item' ), 'permission_callback' => array( $this, 'delete_item_permissions_check' ), 'args' => array( 'force' => array( 'type' => 'boolean', 'default' => false, 'description' => __( 'Required to be true, as terms do not support trashing.' ), ), ), ), 'schema' => array( $this, 'get_public_item_schema' ), ) ); } /** * Checks if a request has access to read terms in the specified taxonomy. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return bool|WP_Error True if the request has read access, otherwise false or WP_Error object. */ public function get_items_permissions_check( $request ) { $tax_obj = get_taxonomy( $this->taxonomy ); if ( ! $tax_obj || ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) { return false; } if ( 'edit' === $request['context'] && ! current_user_can( $tax_obj->cap->edit_terms ) ) { return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit terms in this taxonomy.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Retrieves terms associated with a taxonomy. * * @since 4.7.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 get_items( $request ) { // Retrieve the list of registered collection query parameters. $registered = $this->get_collection_params(); /* * This array defines mappings between public API query parameters whose * values are accepted as-passed, and their internal WP_Query parameter * name equivalents (some are the same). Only values which are also * present in $registered will be set. */ $parameter_mappings = array( 'exclude' => 'exclude', 'include' => 'include', 'order' => 'order', 'orderby' => 'orderby', 'post' => 'post', 'hide_empty' => 'hide_empty', 'per_page' => 'number', 'search' => 'search', 'slug' => 'slug', ); $prepared_args = array(); /* * For each known parameter which is both registered and present in the request, * set the parameter's value on the query $prepared_args. */ foreach ( $parameter_mappings as $api_param => $wp_param ) { if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) { $prepared_args[ $wp_param ] = $request[ $api_param ]; } } if ( isset( $prepared_args['orderby'] ) && isset( $request['orderby'] ) ) { $orderby_mappings = array( 'include_slugs' => 'slug__in', ); if ( isset( $orderby_mappings[ $request['orderby'] ] ) ) { $prepared_args['orderby'] = $orderby_mappings[ $request['orderby'] ]; } } if ( isset( $registered['offset'] ) && ! empty( $request['offset'] ) ) { $prepared_args['offset'] = $request['offset']; } else { $prepared_args['offset'] = ( $request['page'] - 1 ) * $prepared_args['number']; } $taxonomy_obj = get_taxonomy( $this->taxonomy ); if ( $taxonomy_obj->hierarchical && isset( $registered['parent'], $request['parent'] ) ) { if ( 0 === $request['parent'] ) { // Only query top-level terms. $prepared_args['parent'] = 0; } else { if ( $request['parent'] ) { $prepared_args['parent'] = $request['parent']; } } } /** * Filters the query arguments before passing them to get_terms(). * * The dynamic portion of the hook name, `$this->taxonomy`, refers to the taxonomy slug. * * Enables adding extra arguments or setting defaults for a terms * collection request. * * @since 4.7.0 * * @link https://developer.wordpress.org/reference/functions/get_terms/ * * @param array $prepared_args Array of arguments to be * passed to get_terms(). * @param WP_REST_Request $request The current request. */ $prepared_args = apply_filters( "rest_{$this->taxonomy}_query", $prepared_args, $request ); if ( ! empty( $prepared_args['post'] ) ) { $query_result = wp_get_object_terms( $prepared_args['post'], $this->taxonomy, $prepared_args ); // Used when calling wp_count_terms() below. $prepared_args['object_ids'] = $prepared_args['post']; } else { $query_result = get_terms( $this->taxonomy, $prepared_args ); } $count_args = $prepared_args; unset( $count_args['number'], $count_args['offset'] ); $total_terms = wp_count_terms( $this->taxonomy, $count_args ); // wp_count_terms can return a falsy value when the term has no children. if ( ! $total_terms ) { $total_terms = 0; } $response = array(); foreach ( $query_result as $term ) { $data = $this->prepare_item_for_response( $term, $request ); $response[] = $this->prepare_response_for_collection( $data ); } $response = rest_ensure_response( $response ); // Store pagination values for headers. $per_page = (int) $prepared_args['number']; $page = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 ); $response->header( 'X-WP-Total', (int) $total_terms ); $max_pages = ceil( $total_terms / $per_page ); $response->header( 'X-WP-TotalPages', (int) $max_pages ); $base = add_query_arg( $request->get_query_params(), rest_url( $this->namespace . '/' . $this->rest_base ) ); if ( $page > 1 ) { $prev_page = $page - 1; if ( $prev_page > $max_pages ) { $prev_page = $max_pages; } $prev_link = add_query_arg( 'page', $prev_page, $base ); $response->link_header( 'prev', $prev_link ); } if ( $max_pages > $page ) { $next_page = $page + 1; $next_link = add_query_arg( 'page', $next_page, $base ); $response->link_header( 'next', $next_link ); } return $response; } /** * Get the term, if the ID is valid. * * @since 4.7.2 * * @param int $id Supplied ID. * @return WP_Term|WP_Error Term object if ID is valid, WP_Error otherwise. */ protected function get_term( $id ) { $error = new WP_Error( 'rest_term_invalid', __( 'Term does not exist.' ), array( 'status' => 404 ) ); if ( ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) { return $error; } if ( (int) $id <= 0 ) { return $error; } $term = get_term( (int) $id, $this->taxonomy ); if ( empty( $term ) || $term->taxonomy !== $this->taxonomy ) { return $error; } return $term; } /** * Checks if a request has access to read or edit the specified term. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return bool|WP_Error True if the request has read access for the item, otherwise false or WP_Error object. */ public function get_item_permissions_check( $request ) { $term = $this->get_term( $request['id'] ); if ( is_wp_error( $term ) ) { return $term; } if ( 'edit' === $request['context'] && ! current_user_can( 'edit_term', $term->term_id ) ) { return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit this term.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Gets a single term from a taxonomy. * * @since 4.7.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 get_item( $request ) { $term = $this->get_term( $request['id'] ); if ( is_wp_error( $term ) ) { return $term; } $response = $this->prepare_item_for_response( $term, $request ); return rest_ensure_response( $response ); } /** * Checks if a request has access to create a term. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return bool|WP_Error True if the request has access to create items, false or WP_Error object otherwise. */ public function create_item_permissions_check( $request ) { if ( ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) { return false; } $taxonomy_obj = get_taxonomy( $this->taxonomy ); if ( ! current_user_can( $taxonomy_obj->cap->edit_terms ) ) { return new WP_Error( 'rest_cannot_create', __( 'Sorry, you are not allowed to create new terms.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Creates a single term in a taxonomy. * * @since 4.7.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 = 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 ); $term = wp_insert_term( wp_slash( $prepared_term->name ), $this->taxonomy, 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 ( $term_id = $term->get_error_data( 'term_exists' ) ) { $existing_term = get_term( $term_id, $this->taxonomy ); $term->add_data( $existing_term->term_id, 'term_exists' ); $term->add_data( array( 'status' => 409, 'term_id' => $term_id ) ); } return $term; } $term = get_term( $term['term_id'], $this->taxonomy ); /** * Fires after a single term is created or updated via the REST API. * * The dynamic portion of the hook name, `$this->taxonomy`, refers to the taxonomy slug. * * @since 4.7.0 * * @param WP_Term $term Inserted or updated term object. * @param WP_REST_Request $request Request object. * @param bool $creating True when creating a term, false when updating. */ 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'], (int) $request['id'] ); if ( is_wp_error( $meta_update ) ) { return $meta_update; } } $fields_update = $this->update_additional_fields_for_object( $term, $request ); if ( is_wp_error( $fields_update ) ) { return $fields_update; } $request->set_param( 'context', 'view' ); $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; } /** * Checks if a request has access to update the specified term. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return bool|WP_Error True if the request has access to update the item, false or WP_Error object otherwise. */ public function update_item_permissions_check( $request ) { $term = $this->get_term( $request['id'] ); if ( is_wp_error( $term ) ) { return $term; } if ( ! current_user_can( 'edit_term', $term->term_id ) ) { return new WP_Error( 'rest_cannot_update', __( 'Sorry, you are not allowed to edit this term.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Updates a single term from a taxonomy. * * @since 4.7.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 haz something to update. if ( ! empty( $prepared_term ) ) { $update = wp_update_term( $term->term_id, $term->taxonomy, 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; } } $fields_update = $this->update_additional_fields_for_object( $term, $request ); if ( is_wp_error( $fields_update ) ) { return $fields_update; } $request->set_param( 'context', 'view' ); $response = $this->prepare_item_for_response( $term, $request ); return rest_ensure_response( $response ); } /** * Checks if a request has access to delete the specified term. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return bool|WP_Error True if the request has access to delete the item, otherwise false or WP_Error object. */ public function delete_item_permissions_check( $request ) { $term = $this->get_term( $request['id'] ); if ( is_wp_error( $term ) ) { return $term; } if ( ! current_user_can( 'delete_term', $term->term_id ) ) { return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you are not allowed to delete this term.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Deletes a single term from a taxonomy. * * @since 4.7.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; } $force = isset( $request['force'] ) ? (bool) $request['force'] : false; // We don't support trashing for terms. if ( ! $force ) { /* translators: %s: force=true */ return new WP_Error( 'rest_trash_not_supported', sprintf( __( "Terms 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 ); $retval = wp_delete_term( $term->term_id, $term->taxonomy ); if ( ! $retval ) { return new WP_Error( 'rest_cannot_delete', __( 'The term cannot be deleted.' ), array( 'status' => 500 ) ); } $response = new WP_REST_Response(); $response->set_data( array( 'deleted' => true, 'previous' => $previous->get_data() ) ); /** * Fires after a single term is deleted via the REST API. * * The dynamic portion of the hook name, `$this->taxonomy`, refers to the taxonomy slug. * * @since 4.7.0 * * @param WP_Term $term The deleted term. * @param WP_REST_Response $response The response data. * @param WP_REST_Request $request The request sent to the API. */ do_action( "rest_delete_{$this->taxonomy}", $term, $response, $request ); return $response; } /** * Prepares a single term for create or update. * * @since 4.7.0 * * @param WP_REST_Request $request Request object. * @return object $prepared_term Term object. */ public function prepare_item_for_database( $request ) { $prepared_term = new stdClass; $schema = $this->get_item_schema(); if ( isset( $request['name'] ) && ! empty( $schema['properties']['name'] ) ) { $prepared_term->name = $request['name']; } if ( isset( $request['slug'] ) && ! empty( $schema['properties']['slug'] ) ) { $prepared_term->slug = $request['slug']; } if ( isset( $request['taxonomy'] ) && ! empty( $schema['properties']['taxonomy'] ) ) { $prepared_term->taxonomy = $request['taxonomy']; } if ( isset( $request['description'] ) && ! empty( $schema['properties']['description'] ) ) { $prepared_term->description = $request['description']; } if ( isset( $request['parent'] ) && ! empty( $schema['properties']['parent'] ) ) { $parent_term_id = 0; $parent_term = get_term( (int) $request['parent'], $this->taxonomy ); if ( $parent_term ) { $parent_term_id = $parent_term->term_id; } $prepared_term->parent = $parent_term_id; } /** * Filters term data before inserting term via the REST API. * * The dynamic portion of the hook name, `$this->taxonomy`, refers to the taxonomy slug. * * @since 4.7.0 * * @param object $prepared_term Term object. * @param WP_REST_Request $request Request object. */ return apply_filters( "rest_pre_insert_{$this->taxonomy}", $prepared_term, $request ); } /** * Prepares a single term output for response. * * @since 4.7.0 * * @param obj $item Term object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response $response Response object. */ public function prepare_item_for_response( $item, $request ) { $schema = $this->get_item_schema(); $data = array(); if ( ! empty( $schema['properties']['id'] ) ) { $data['id'] = (int) $item->term_id; } if ( ! empty( $schema['properties']['count'] ) ) { $data['count'] = (int) $item->count; } if ( ! empty( $schema['properties']['description'] ) ) { $data['description'] = $item->description; } if ( ! empty( $schema['properties']['link'] ) ) { $data['link'] = get_term_link( $item ); } if ( ! empty( $schema['properties']['name'] ) ) { $data['name'] = $item->name; } if ( ! empty( $schema['properties']['slug'] ) ) { $data['slug'] = $item->slug; } if ( ! empty( $schema['properties']['taxonomy'] ) ) { $data['taxonomy'] = $item->taxonomy; } if ( ! empty( $schema['properties']['parent'] ) ) { $data['parent'] = (int) $item->parent; } if ( ! empty( $schema['properties']['meta'] ) ) { $data['meta'] = $this->meta->get_value( $item->term_id, $request ); } $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 ); $response->add_links( $this->prepare_links( $item ) ); /** * Filters a term item returned from the API. * * The dynamic portion of the hook name, `$this->taxonomy`, refers to the taxonomy slug. * * Allows modification of the term data right before it is returned. * * @since 4.7.0 * * @param WP_REST_Response $response The response object. * @param object $item The original term object. * @param WP_REST_Request $request Request used to generate the response. */ return apply_filters( "rest_prepare_{$this->taxonomy}", $response, $item, $request ); } /** * Prepares links for the request. * * @since 4.7.0 * * @param object $term Term object. * @return array Links for the given term. */ protected function prepare_links( $term ) { $base = $this->namespace . '/' . $this->rest_base; $links = array( 'self' => array( 'href' => rest_url( trailingslashit( $base ) . $term->term_id ), ), 'collection' => array( 'href' => rest_url( $base ), ), 'about' => array( 'href' => rest_url( sprintf( 'wp/v2/taxonomies/%s', $this->taxonomy ) ), ), ); if ( $term->parent ) { $parent_term = get_term( (int) $term->parent, $term->taxonomy ); if ( $parent_term ) { $links['up'] = array( 'href' => rest_url( trailingslashit( $base ) . $parent_term->term_id ), 'embeddable' => true, ); } } $taxonomy_obj = get_taxonomy( $term->taxonomy ); if ( empty( $taxonomy_obj->object_type ) ) { return $links; } $post_type_links = array(); foreach ( $taxonomy_obj->object_type as $type ) { $post_type_object = get_post_type_object( $type ); if ( empty( $post_type_object->show_in_rest ) ) { continue; } $rest_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name; $post_type_links[] = array( 'href' => add_query_arg( $this->rest_base, $term->term_id, rest_url( sprintf( 'wp/v2/%s', $rest_base ) ) ), ); } if ( ! empty( $post_type_links ) ) { $links['https://api.w.org/post_type'] = $post_type_links; } return $links; } /** * Retrieves the term's schema, conforming to JSON Schema. * * @since 4.7.0 * * @return array Item schema data. */ public function get_item_schema() { $schema = array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'post_tag' === $this->taxonomy ? 'tag' : $this->taxonomy, 'type' => 'object', 'properties' => array( 'id' => array( 'description' => __( 'Unique identifier for the term.' ), 'type' => 'integer', 'context' => array( 'view', 'embed', 'edit' ), 'readonly' => true, ), 'count' => array( 'description' => __( 'Number of published posts for the term.' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'description' => array( 'description' => __( 'HTML description of the term.' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), ), 'link' => array( 'description' => __( 'URL of the term.' ), 'type' => 'string', 'format' => 'uri', 'context' => array( 'view', 'embed', 'edit' ), 'readonly' => true, ), 'name' => array( 'description' => __( 'HTML title for the term.' ), 'type' => 'string', 'context' => array( 'view', 'embed', 'edit' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), 'required' => true, ), 'slug' => array( 'description' => __( 'An alphanumeric identifier for the term unique to its type.' ), 'type' => 'string', 'context' => array( 'view', 'embed', 'edit' ), 'arg_options' => array( 'sanitize_callback' => array( $this, 'sanitize_slug' ), ), ), 'taxonomy' => array( 'description' => __( 'Type attribution for the term.' ), 'type' => 'string', 'enum' => array_keys( get_taxonomies() ), 'context' => array( 'view', 'embed', 'edit' ), 'readonly' => true, ), ), ); $taxonomy = get_taxonomy( $this->taxonomy ); if ( $taxonomy->hierarchical ) { $schema['properties']['parent'] = array( 'description' => __( 'The parent term ID.' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), ); } $schema['properties']['meta'] = $this->meta->get_field_schema(); return $this->add_additional_fields_schema( $schema ); } /** * Retrieves the query params for collections. * * @since 4.7.0 * * @return array Collection parameters. */ public function get_collection_params() { $query_params = parent::get_collection_params(); $taxonomy = get_taxonomy( $this->taxonomy ); $query_params['context']['default'] = 'view'; $query_params['exclude'] = array( 'description' => __( 'Ensure result set excludes specific IDs.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'default' => array(), ); $query_params['include'] = array( 'description' => __( 'Limit result set to specific IDs.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'default' => array(), ); if ( ! $taxonomy->hierarchical ) { $query_params['offset'] = array( 'description' => __( 'Offset the result set by a specific number of items.' ), 'type' => 'integer', ); } $query_params['order'] = array( 'description' => __( 'Order sort attribute ascending or descending.' ), 'type' => 'string', 'default' => 'asc', 'enum' => array( 'asc', 'desc', ), ); $query_params['orderby'] = array( 'description' => __( 'Sort collection by term attribute.' ), 'type' => 'string', 'default' => 'name', 'enum' => array( 'id', 'include', 'name', 'slug', 'include_slugs', 'term_group', 'description', 'count', ), ); $query_params['hide_empty'] = array( 'description' => __( 'Whether to hide terms not assigned to any posts.' ), 'type' => 'boolean', 'default' => false, ); if ( $taxonomy->hierarchical ) { $query_params['parent'] = array( 'description' => __( 'Limit result set to terms assigned to a specific parent.' ), 'type' => 'integer', ); } $query_params['post'] = array( 'description' => __( 'Limit result set to terms assigned to a specific post.' ), 'type' => 'integer', 'default' => null, ); $query_params['slug'] = array( 'description' => __( 'Limit result set to terms with one or more specific slugs.' ), 'type' => 'array', 'items' => array( 'type' => 'string' ), ); /** * Filter collection parameters for the terms controller. * * The dynamic part of the filter `$this->taxonomy` refers to the taxonomy * slug for the controller. * * This filter registers the collection parameter, but does not map the * collection parameter to an internal WP_Term_Query parameter. Use the * `rest_{$this->taxonomy}_query` filter to set WP_Term_Query parameters. * * @since 4.7.0 * * @param array $query_params JSON Schema-formatted collection parameters. * @param WP_Taxonomy $taxonomy Taxonomy object. */ return apply_filters( "rest_{$this->taxonomy}_collection_params", $query_params, $taxonomy ); } /** * Checks that the taxonomy is valid. * * @since 4.7.0 * * @param string $taxonomy Taxonomy to check. * @return bool Whether the taxonomy is allowed for REST management. */ protected function check_is_taxonomy_allowed( $taxonomy ) { $taxonomy_obj = get_taxonomy( $taxonomy ); if ( $taxonomy_obj && ! empty( $taxonomy_obj->show_in_rest ) ) { return true; } return false; } } /** * REST API: WP_REST_Users_Controller class * * @package WordPress * @subpackage REST_API * @since 4.7.0 */ /** * Core class used to manage users via the REST API. * * @since 4.7.0 * * @see WP_REST_Controller */ class WP_REST_Users_Controller extends WP_REST_Controller { /** * Instance of a user meta fields object. * * @since 4.7.0 * @var WP_REST_User_Meta_Fields */ protected $meta; /** * Constructor. * * @since 4.7.0 */ public function __construct() { $this->namespace = 'wp/v2'; $this->rest_base = 'users'; $this->meta = new WP_REST_User_Meta_Fields(); } /** * Registers the routes for the objects of the controller. * * @since 4.7.0 * * @see register_rest_route() */ public function register_routes() { register_rest_route( $this->namespace, '/' . $this->rest_base, array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_items' ), 'permission_callback' => array( $this, 'get_items_permissions_check' ), 'args' => $this->get_collection_params(), ), array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'create_item' ), 'permission_callback' => array( $this, 'create_item_permissions_check' ), 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), ), 'schema' => array( $this, 'get_public_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[\d]+)', array( 'args' => array( 'id' => array( 'description' => __( 'Unique identifier for the user.' ), 'type' => 'integer', ), ), array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_item' ), 'permission_callback' => array( $this, 'get_item_permissions_check' ), 'args' => array( 'context' => $this->get_context_param( array( 'default' => 'view' ) ), ), ), array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'update_item' ), 'permission_callback' => array( $this, 'update_item_permissions_check' ), 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), ), array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => array( $this, 'delete_item' ), 'permission_callback' => array( $this, 'delete_item_permissions_check' ), 'args' => array( 'force' => array( 'type' => 'boolean', 'default' => false, 'description' => __( 'Required to be true, as users do not support trashing.' ), ), 'reassign' => array( 'type' => 'integer', 'description' => __( 'Reassign the deleted user\'s posts and links to this user ID.' ), 'required' => true, 'sanitize_callback' => array( $this, 'check_reassign' ), ), ), ), 'schema' => array( $this, 'get_public_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/me', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_current_item' ), 'args' => array( 'context' => $this->get_context_param( array( 'default' => 'view' ) ), ), ), array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'update_current_item' ), 'permission_callback' => array( $this, 'update_current_item_permissions_check' ), 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), ), array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => array( $this, 'delete_current_item' ), 'permission_callback' => array( $this, 'delete_current_item_permissions_check' ), 'args' => array( 'force' => array( 'type' => 'boolean', 'default' => false, 'description' => __( 'Required to be true, as users do not support trashing.' ), ), 'reassign' => array( 'type' => 'integer', 'description' => __( 'Reassign the deleted user\'s posts and links to this user ID.' ), 'required' => true, 'sanitize_callback' => array( $this, 'check_reassign' ), ), ), ), 'schema' => array( $this, 'get_public_item_schema' ), )); } /** * Checks for a valid value for the reassign parameter when deleting users. * * The value can be an integer, 'false', false, or ''. * * @since 4.7.0 * * @param int|bool $value The value passed to the reassign parameter. * @param WP_REST_Request $request Full details about the request. * @param string $param The parameter that is being sanitized. * * @return int|bool|WP_Error */ public function check_reassign( $value, $request, $param ) { if ( is_numeric( $value ) ) { return $value; } if ( empty( $value ) || false === $value || 'false' === $value ) { return false; } return new WP_Error( 'rest_invalid_param', __( 'Invalid user parameter(s).' ), array( 'status' => 400 ) ); } /** * Permissions check for getting all users. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has read access, otherwise WP_Error object. */ public function get_items_permissions_check( $request ) { // Check if roles is specified in GET request and if user can list users. if ( ! empty( $request['roles'] ) && ! current_user_can( 'list_users' ) ) { return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to filter users by role.' ), array( 'status' => rest_authorization_required_code() ) ); } if ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) { return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) ); } if ( in_array( $request['orderby'], array( 'email', 'registered_date' ), true ) && ! current_user_can( 'list_users' ) ) { return new WP_Error( 'rest_forbidden_orderby', __( 'Sorry, you are not allowed to order users by this parameter.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Retrieves all users. * * @since 4.7.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 get_items( $request ) { // Retrieve the list of registered collection query parameters. $registered = $this->get_collection_params(); /* * This array defines mappings between public API query parameters whose * values are accepted as-passed, and their internal WP_Query parameter * name equivalents (some are the same). Only values which are also * present in $registered will be set. */ $parameter_mappings = array( 'exclude' => 'exclude', 'include' => 'include', 'order' => 'order', 'per_page' => 'number', 'search' => 'search', 'roles' => 'role__in', 'slug' => 'nicename__in', ); $prepared_args = array(); /* * For each known parameter which is both registered and present in the request, * set the parameter's value on the query $prepared_args. */ foreach ( $parameter_mappings as $api_param => $wp_param ) { if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) { $prepared_args[ $wp_param ] = $request[ $api_param ]; } } if ( isset( $registered['offset'] ) && ! empty( $request['offset'] ) ) { $prepared_args['offset'] = $request['offset']; } else { $prepared_args['offset'] = ( $request['page'] - 1 ) * $prepared_args['number']; } if ( isset( $registered['orderby'] ) ) { $orderby_possibles = array( 'id' => 'ID', 'include' => 'include', 'name' => 'display_name', 'registered_date' => 'registered', 'slug' => 'user_nicename', 'include_slugs' => 'nicename__in', 'email' => 'user_email', 'url' => 'user_url', ); $prepared_args['orderby'] = $orderby_possibles[ $request['orderby'] ]; } if ( ! current_user_can( 'list_users' ) ) { $prepared_args['has_published_posts'] = get_post_types( array( 'show_in_rest' => true ), 'names' ); } if ( ! empty( $prepared_args['search'] ) ) { $prepared_args['search'] = '*' . $prepared_args['search'] . '*'; } /** * Filters WP_User_Query arguments when querying users via the REST API. * * @link https://developer.wordpress.org/reference/classes/wp_user_query/ * * @since 4.7.0 * * @param array $prepared_args Array of arguments for WP_User_Query. * @param WP_REST_Request $request The current request. */ $prepared_args = apply_filters( 'rest_user_query', $prepared_args, $request ); $query = new WP_User_Query( $prepared_args ); $users = array(); foreach ( $query->results as $user ) { $data = $this->prepare_item_for_response( $user, $request ); $users[] = $this->prepare_response_for_collection( $data ); } $response = rest_ensure_response( $users ); // Store pagination values for headers then unset for count query. $per_page = (int) $prepared_args['number']; $page = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 ); $prepared_args['fields'] = 'ID'; $total_users = $query->get_total(); if ( $total_users < 1 ) { // Out-of-bounds, run the query again without LIMIT for total count. unset( $prepared_args['number'], $prepared_args['offset'] ); $count_query = new WP_User_Query( $prepared_args ); $total_users = $count_query->get_total(); } $response->header( 'X-WP-Total', (int) $total_users ); $max_pages = ceil( $total_users / $per_page ); $response->header( 'X-WP-TotalPages', (int) $max_pages ); $base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ) ); if ( $page > 1 ) { $prev_page = $page - 1; if ( $prev_page > $max_pages ) { $prev_page = $max_pages; } $prev_link = add_query_arg( 'page', $prev_page, $base ); $response->link_header( 'prev', $prev_link ); } if ( $max_pages > $page ) { $next_page = $page + 1; $next_link = add_query_arg( 'page', $next_page, $base ); $response->link_header( 'next', $next_link ); } return $response; } /** * Get the user, if the ID is valid. * * @since 4.7.2 * * @param int $id Supplied ID. * @return WP_User|WP_Error True if ID is valid, WP_Error otherwise. */ protected function get_user( $id ) { $error = new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) ); if ( (int) $id <= 0 ) { return $error; } $user = get_userdata( (int) $id ); if ( empty( $user ) || ! $user->exists() ) { return $error; } if ( is_multisite() && ! is_user_member_of_blog( $user->ID ) ) { return $error; } return $user; } /** * Checks if a given request has access to read a user. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has read access for the item, otherwise WP_Error object. */ public function get_item_permissions_check( $request ) { $user = $this->get_user( $request['id'] ); if ( is_wp_error( $user ) ) { return $user; } $types = get_post_types( array( 'show_in_rest' => true ), 'names' ); if ( get_current_user_id() === $user->ID ) { return true; } if ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) { return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) ); } elseif ( ! count_user_posts( $user->ID, $types ) && ! current_user_can( 'edit_user', $user->ID ) && ! current_user_can( 'list_users' ) ) { return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Retrieves a single user. * * @since 4.7.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 get_item( $request ) { $user = $this->get_user( $request['id'] ); if ( is_wp_error( $user ) ) { return $user; } $user = $this->prepare_item_for_response( $user, $request ); $response = rest_ensure_response( $user ); return $response; } /** * Retrieves the current user. * * @since 4.7.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 get_current_item( $request ) { $current_user_id = get_current_user_id(); if ( empty( $current_user_id ) ) { return new WP_Error( 'rest_not_logged_in', __( 'You are not currently logged in.' ), array( 'status' => 401 ) ); } $user = wp_get_current_user(); $response = $this->prepare_item_for_response( $user, $request ); $response = rest_ensure_response( $response ); return $response; } /** * Checks if a given request has access create users. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. */ public function create_item_permissions_check( $request ) { if ( ! current_user_can( 'create_users' ) ) { return new WP_Error( 'rest_cannot_create_user', __( 'Sorry, you are not allowed to create new users.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Creates a single user. * * @since 4.7.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 ( ! empty( $request['id'] ) ) { return new WP_Error( 'rest_user_exists', __( 'Cannot create existing user.' ), array( 'status' => 400 ) ); } $schema = $this->get_item_schema(); if ( ! empty( $request['roles'] ) && ! empty( $schema['properties']['roles'] ) ) { $check_permission = $this->check_role_update( $request['id'], $request['roles'] ); if ( is_wp_error( $check_permission ) ) { return $check_permission; } } $user = $this->prepare_item_for_database( $request ); if ( is_multisite() ) { $ret = wpmu_validate_user_signup( $user->user_login, $user->user_email ); if ( is_wp_error( $ret['errors'] ) && ! empty( $ret['errors']->errors ) ) { $error = new WP_Error( 'rest_invalid_param', __( 'Invalid user parameter(s).' ), array( 'status' => 400 ) ); foreach ( $ret['errors']->errors as $code => $messages ) { foreach ( $messages as $message ) { $error->add( $code, $message ); } if ( $error_data = $error->get_error_data( $code ) ) { $error->add_data( $error_data, $code ); } } return $error; } } if ( is_multisite() ) { $user_id = wpmu_create_user( $user->user_login, $user->user_pass, $user->user_email ); if ( ! $user_id ) { return new WP_Error( 'rest_user_create', __( 'Error creating new user.' ), array( 'status' => 500 ) ); } $user->ID = $user_id; $user_id = wp_update_user( wp_slash( (array) $user ) ); if ( is_wp_error( $user_id ) ) { return $user_id; } $result= add_user_to_blog( get_site()->id, $user_id, '' ); if ( is_wp_error( $result ) ) { return $result; } } else { $user_id = wp_insert_user( wp_slash( (array) $user ) ); if ( is_wp_error( $user_id ) ) { return $user_id; } } $user = get_user_by( 'id', $user_id ); /** * Fires immediately after a user is created or updated via the REST API. * * @since 4.7.0 * * @param WP_User $user Inserted or updated user object. * @param WP_REST_Request $request Request object. * @param bool $creating True when creating a user, false when updating. */ do_action( 'rest_insert_user', $user, $request, true ); if ( ! empty( $request['roles'] ) && ! empty( $schema['properties']['roles'] ) ) { array_map( array( $user, 'add_role' ), $request['roles'] ); } if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) { $meta_update = $this->meta->update_value( $request['meta'], $user_id ); if ( is_wp_error( $meta_update ) ) { return $meta_update; } } $user = get_user_by( 'id', $user_id ); $fields_update = $this->update_additional_fields_for_object( $user, $request ); if ( is_wp_error( $fields_update ) ) { return $fields_update; } $request->set_param( 'context', 'edit' ); $response = $this->prepare_item_for_response( $user, $request ); $response = rest_ensure_response( $response ); $response->set_status( 201 ); $response->header( 'Location', rest_url( sprintf( '%s/%s/%d', $this->namespace, $this->rest_base, $user_id ) ) ); return $response; } /** * Checks if a given request has access to update a user. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. */ public function update_item_permissions_check( $request ) { $user = $this->get_user( $request['id'] ); if ( is_wp_error( $user ) ) { return $user; } if ( ! empty( $request['roles'] ) ) { if ( ! current_user_can( 'promote_user', $user->ID ) ) { return new WP_Error( 'rest_cannot_edit_roles', __( 'Sorry, you are not allowed to edit roles of this user.' ), array( 'status' => rest_authorization_required_code() ) ); } $request_params = array_keys( $request->get_params() ); sort( $request_params ); // If only 'id' and 'roles' are specified (we are only trying to // edit roles), then only the 'promote_user' cap is required. if ( $request_params === array( 'id', 'roles' ) ) { return true; } } if ( ! current_user_can( 'edit_user', $user->ID ) ) { return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this user.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Updates a single user. * * @since 4.7.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 ) { $user = $this->get_user( $request['id'] ); if ( is_wp_error( $user ) ) { return $user; } $id = $user->ID; if ( ! $user ) { return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) ); } if ( email_exists( $request['email'] ) && $request['email'] !== $user->user_email ) { return new WP_Error( 'rest_user_invalid_email', __( 'Invalid email address.' ), array( 'status' => 400 ) ); } if ( ! empty( $request['username'] ) && $request['username'] !== $user->user_login ) { return new WP_Error( 'rest_user_invalid_argument', __( "Username isn't editable." ), array( 'status' => 400 ) ); } if ( ! empty( $request['slug'] ) && $request['slug'] !== $user->user_nicename && get_user_by( 'slug', $request['slug'] ) ) { return new WP_Error( 'rest_user_invalid_slug', __( 'Invalid slug.' ), array( 'status' => 400 ) ); } if ( ! empty( $request['roles'] ) ) { $check_permission = $this->check_role_update( $id, $request['roles'] ); if ( is_wp_error( $check_permission ) ) { return $check_permission; } } $user = $this->prepare_item_for_database( $request ); // Ensure we're operating on the same user we already checked. $user->ID = $id; $user_id = wp_update_user( wp_slash( (array) $user ) ); if ( is_wp_error( $user_id ) ) { return $user_id; } $user = get_user_by( 'id', $user_id ); /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php */ do_action( 'rest_insert_user', $user, $request, false ); if ( ! empty( $request['roles'] ) ) { array_map( array( $user, 'add_role' ), $request['roles'] ); } $schema = $this->get_item_schema(); if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) { $meta_update = $this->meta->update_value( $request['meta'], $id ); if ( is_wp_error( $meta_update ) ) { return $meta_update; } } $user = get_user_by( 'id', $user_id ); $fields_update = $this->update_additional_fields_for_object( $user, $request ); if ( is_wp_error( $fields_update ) ) { return $fields_update; } $request->set_param( 'context', 'edit' ); $response = $this->prepare_item_for_response( $user, $request ); $response = rest_ensure_response( $response ); return $response; } /** * Checks if a given request has access to update the current user. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. */ public function update_current_item_permissions_check( $request ) { $request['id'] = get_current_user_id(); return $this->update_item_permissions_check( $request ); } /** * Updates the current user. * * @since 4.7.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. */ function update_current_item( $request ) { $request['id'] = get_current_user_id(); return $this->update_item( $request ); } /** * Checks if a given request has access delete a user. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise. */ public function delete_item_permissions_check( $request ) { $user = $this->get_user( $request['id'] ); if ( is_wp_error( $user ) ) { return $user; } if ( ! current_user_can( 'delete_user', $user->ID ) ) { return new WP_Error( 'rest_user_cannot_delete', __( 'Sorry, you are not allowed to delete this user.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Deletes a single user. * * @since 4.7.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 ) { // We don't support delete requests in multisite. if ( is_multisite() ) { return new WP_Error( 'rest_cannot_delete', __( 'The user cannot be deleted.' ), array( 'status' => 501 ) ); } $user = $this->get_user( $request['id'] ); if ( is_wp_error( $user ) ) { return $user; } $id = $user->ID; $reassign = false === $request['reassign'] ? null : absint( $request['reassign'] ); $force = isset( $request['force'] ) ? (bool) $request['force'] : false; // We don't support trashing for users. if ( ! $force ) { /* translators: %s: force=true */ return new WP_Error( 'rest_trash_not_supported', sprintf( __( "Users do not support trashing. Set '%s' to delete." ), 'force=true' ), array( 'status' => 501 ) ); } if ( ! empty( $reassign ) ) { if ( $reassign === $id || ! get_userdata( $reassign ) ) { return new WP_Error( 'rest_user_invalid_reassign', __( 'Invalid user ID for reassignment.' ), array( 'status' => 400 ) ); } } $request->set_param( 'context', 'edit' ); $previous = $this->prepare_item_for_response( $user, $request ); /** Include admin user functions to get access to wp_delete_user() */ require_once ABSPATH . 'wp-admin/includes/user.php'; $result = wp_delete_user( $id, $reassign ); if ( ! $result ) { return new WP_Error( 'rest_cannot_delete', __( 'The user cannot be deleted.' ), array( 'status' => 500 ) ); } $response = new WP_REST_Response(); $response->set_data( array( 'deleted' => true, 'previous' => $previous->get_data() ) ); /** * Fires immediately after a user is deleted via the REST API. * * @since 4.7.0 * * @param WP_User $user The user data. * @param WP_REST_Response $response The response returned from the API. * @param WP_REST_Request $request The request sent to the API. */ do_action( 'rest_delete_user', $user, $response, $request ); return $response; } /** * Checks if a given request has access to delete the current user. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise. */ public function delete_current_item_permissions_check( $request ) { $request['id'] = get_current_user_id(); return $this->delete_item_permissions_check( $request ); } /** * Deletes the current user. * * @since 4.7.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. */ function delete_current_item( $request ) { $request['id'] = get_current_user_id(); return $this->delete_item( $request ); } /** * Prepares a single user output for response. * * @since 4.7.0 * * @param WP_User $user User object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ public function prepare_item_for_response( $user, $request ) { $data = array(); $schema = $this->get_item_schema(); if ( ! empty( $schema['properties']['id'] ) ) { $data['id'] = $user->ID; } if ( ! empty( $schema['properties']['username'] ) ) { $data['username'] = $user->user_login; } if ( ! empty( $schema['properties']['name'] ) ) { $data['name'] = $user->display_name; } if ( ! empty( $schema['properties']['first_name'] ) ) { $data['first_name'] = $user->first_name; } if ( ! empty( $schema['properties']['last_name'] ) ) { $data['last_name'] = $user->last_name; } if ( ! empty( $schema['properties']['email'] ) ) { $data['email'] = $user->user_email; } if ( ! empty( $schema['properties']['url'] ) ) { $data['url'] = $user->user_url; } if ( ! empty( $schema['properties']['description'] ) ) { $data['description'] = $user->description; } if ( ! empty( $schema['properties']['link'] ) ) { $data['link'] = get_author_posts_url( $user->ID, $user->user_nicename ); } if ( ! empty( $schema['properties']['locale'] ) ) { $data['locale'] = get_user_locale( $user ); } if ( ! empty( $schema['properties']['nickname'] ) ) { $data['nickname'] = $user->nickname; } if ( ! empty( $schema['properties']['slug'] ) ) { $data['slug'] = $user->user_nicename; } if ( ! empty( $schema['properties']['roles'] ) ) { // Defensively call array_values() to ensure an array is returned. $data['roles'] = array_values( $user->roles ); } if ( ! empty( $schema['properties']['registered_date'] ) ) { $data['registered_date'] = date( 'c', strtotime( $user->user_registered ) ); } if ( ! empty( $schema['properties']['capabilities'] ) ) { $data['capabilities'] = (object) $user->allcaps; } if ( ! empty( $schema['properties']['extra_capabilities'] ) ) { $data['extra_capabilities'] = (object) $user->caps; } if ( ! empty( $schema['properties']['avatar_urls'] ) ) { $data['avatar_urls'] = rest_get_avatar_urls( $user->user_email ); } if ( ! empty( $schema['properties']['meta'] ) ) { $data['meta'] = $this->meta->get_value( $user->ID, $request ); } $context = ! empty( $request['context'] ) ? $request['context'] : 'embed'; $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 ); $response->add_links( $this->prepare_links( $user ) ); /** * Filters user data returned from the REST API. * * @since 4.7.0 * * @param WP_REST_Response $response The response object. * @param object $user User object used to create response. * @param WP_REST_Request $request Request object. */ return apply_filters( 'rest_prepare_user', $response, $user, $request ); } /** * Prepares links for the user request. * * @since 4.7.0 * * @param WP_Post $user User object. * @return array Links for the given user. */ protected function prepare_links( $user ) { $links = array( 'self' => array( 'href' => rest_url( sprintf( '%s/%s/%d', $this->namespace, $this->rest_base, $user->ID ) ), ), 'collection' => array( 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), ), ); return $links; } /** * Prepares a single user for creation or update. * * @since 4.7.0 * * @param WP_REST_Request $request Request object. * @return object $prepared_user User object. */ protected function prepare_item_for_database( $request ) { $prepared_user = new stdClass; $schema = $this->get_item_schema(); // required arguments. if ( isset( $request['email'] ) && ! empty( $schema['properties']['email'] ) ) { $prepared_user->user_email = $request['email']; } if ( isset( $request['username'] ) && ! empty( $schema['properties']['username'] ) ) { $prepared_user->user_login = $request['username']; } if ( isset( $request['password'] ) && ! empty( $schema['properties']['password'] ) ) { $prepared_user->user_pass = $request['password']; } // optional arguments. if ( isset( $request['id'] ) ) { $prepared_user->ID = absint( $request['id'] ); } if ( isset( $request['name'] ) && ! empty( $schema['properties']['name'] ) ) { $prepared_user->display_name = $request['name']; } if ( isset( $request['first_name'] ) && ! empty( $schema['properties']['first_name'] ) ) { $prepared_user->first_name = $request['first_name']; } if ( isset( $request['last_name'] ) && ! empty( $schema['properties']['last_name'] ) ) { $prepared_user->last_name = $request['last_name']; } if ( isset( $request['nickname'] ) && ! empty( $schema['properties']['nickname'] ) ) { $prepared_user->nickname = $request['nickname']; } if ( isset( $request['slug'] ) && ! empty( $schema['properties']['slug'] ) ) { $prepared_user->user_nicename = $request['slug']; } if ( isset( $request['description'] ) && ! empty( $schema['properties']['description'] ) ) { $prepared_user->description = $request['description']; } if ( isset( $request['url'] ) && ! empty( $schema['properties']['url'] ) ) { $prepared_user->user_url = $request['url']; } if ( isset( $request['locale'] ) && ! empty( $schema['properties']['locale'] ) ) { $prepared_user->locale = $request['locale']; } // setting roles will be handled outside of this function. if ( isset( $request['roles'] ) ) { $prepared_user->role = false; } /** * Filters user data before insertion via the REST API. * * @since 4.7.0 * * @param object $prepared_user User object. * @param WP_REST_Request $request Request object. */ return apply_filters( 'rest_pre_insert_user', $prepared_user, $request ); } /** * Determines if the current user is allowed to make the desired roles change. * * @since 4.7.0 * * @param integer $user_id User ID. * @param array $roles New user roles. * @return true|WP_Error True if the current user is allowed to make the role change, * otherwise a WP_Error object. */ protected function check_role_update( $user_id, $roles ) { global $wp_roles; foreach ( $roles as $role ) { if ( ! isset( $wp_roles->role_objects[ $role ] ) ) { /* translators: %s: role key */ return new WP_Error( 'rest_user_invalid_role', sprintf( __( 'The role %s does not exist.' ), $role ), array( 'status' => 400 ) ); } $potential_role = $wp_roles->role_objects[ $role ]; /* * Don't let anyone with 'edit_users' (admins) edit their own role to something without it. * Multisite super admins can freely edit their blog roles -- they possess all caps. */ if ( ! ( is_multisite() && current_user_can( 'manage_sites' ) ) && get_current_user_id() === $user_id && ! $potential_role->has_cap( 'edit_users' ) ) { return new WP_Error( 'rest_user_invalid_role', __( 'Sorry, you are not allowed to give users that role.' ), array( 'status' => rest_authorization_required_code() ) ); } /** Include admin functions to get access to get_editable_roles() */ require_once ABSPATH . 'wp-admin/includes/admin.php'; // The new role must be editable by the logged-in user. $editable_roles = get_editable_roles(); if ( empty( $editable_roles[ $role ] ) ) { return new WP_Error( 'rest_user_invalid_role', __( 'Sorry, you are not allowed to give users that role.' ), array( 'status' => 403 ) ); } } return true; } /** * Check a username for the REST API. * * Performs a couple of checks like edit_user() in wp-admin/includes/user.php. * * @since 4.7.0 * * @param mixed $value The username submitted in the request. * @param WP_REST_Request $request Full details about the request. * @param string $param The parameter name. * @return WP_Error|string The sanitized username, if valid, otherwise an error. */ public function check_username( $value, $request, $param ) { $username = (string) $value; if ( ! validate_username( $username ) ) { return new WP_Error( 'rest_user_invalid_username', __( 'Username contains invalid characters.' ), array( 'status' => 400 ) ); } /** This filter is documented in wp-includes/user.php */ $illegal_logins = (array) apply_filters( 'illegal_user_logins', array() ); if ( in_array( strtolower( $username ), array_map( 'strtolower', $illegal_logins ) ) ) { return new WP_Error( 'rest_user_invalid_username', __( 'Sorry, that username is not allowed.' ), array( 'status' => 400 ) ); } return $username; } /** * Check a user password for the REST API. * * Performs a couple of checks like edit_user() in wp-admin/includes/user.php. * * @since 4.7.0 * * @param mixed $value The password submitted in the request. * @param WP_REST_Request $request Full details about the request. * @param string $param The parameter name. * @return WP_Error|string The sanitized password, if valid, otherwise an error. */ public function check_user_password( $value, $request, $param ) { $password = (string) $value; if ( empty( $password ) ) { return new WP_Error( 'rest_user_invalid_password', __( 'Passwords cannot be empty.' ), array( 'status' => 400 ) ); } if ( false !== strpos( $password, "\\" ) ) { return new WP_Error( 'rest_user_invalid_password', __( 'Passwords cannot contain the "\\" character.' ), array( 'status' => 400 ) ); } return $password; } /** * Retrieves the user's schema, conforming to JSON Schema. * * @since 4.7.0 * * @return array Item schema data. */ public function get_item_schema() { $schema = array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'user', 'type' => 'object', 'properties' => array( 'id' => array( 'description' => __( 'Unique identifier for the user.' ), 'type' => 'integer', 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), 'username' => array( 'description' => __( 'Login name for the user.' ), 'type' => 'string', 'context' => array( 'edit' ), 'required' => true, 'arg_options' => array( 'sanitize_callback' => array( $this, 'check_username' ), ), ), 'name' => array( 'description' => __( 'Display name for the user.' ), 'type' => 'string', 'context' => array( 'embed', 'view', 'edit' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ), 'first_name' => array( 'description' => __( 'First name for the user.' ), 'type' => 'string', 'context' => array( 'edit' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ), 'last_name' => array( 'description' => __( 'Last name for the user.' ), 'type' => 'string', 'context' => array( 'edit' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ), 'email' => array( 'description' => __( 'The email address for the user.' ), 'type' => 'string', 'format' => 'email', 'context' => array( 'edit' ), 'required' => true, ), 'url' => array( 'description' => __( 'URL of the user.' ), 'type' => 'string', 'format' => 'uri', 'context' => array( 'embed', 'view', 'edit' ), ), 'description' => array( 'description' => __( 'Description of the user.' ), 'type' => 'string', 'context' => array( 'embed', 'view', 'edit' ), ), 'link' => array( 'description' => __( 'Author URL of the user.' ), 'type' => 'string', 'format' => 'uri', 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), 'locale' => array( 'description' => __( 'Locale for the user.' ), 'type' => 'string', 'enum' => array_merge( array( '', 'en_US' ), get_available_languages() ), 'context' => array( 'edit' ), ), 'nickname' => array( 'description' => __( 'The nickname for the user.' ), 'type' => 'string', 'context' => array( 'edit' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ), 'slug' => array( 'description' => __( 'An alphanumeric identifier for the user.' ), 'type' => 'string', 'context' => array( 'embed', 'view', 'edit' ), 'arg_options' => array( 'sanitize_callback' => array( $this, 'sanitize_slug' ), ), ), 'registered_date' => array( 'description' => __( 'Registration date for the user.' ), 'type' => 'string', 'format' => 'date-time', 'context' => array( 'edit' ), 'readonly' => true, ), 'roles' => array( 'description' => __( 'Roles assigned to the user.' ), 'type' => 'array', 'items' => array( 'type' => 'string', ), 'context' => array( 'edit' ), ), 'password' => array( 'description' => __( 'Password for the user (never included).' ), 'type' => 'string', 'context' => array(), // Password is never displayed. 'required' => true, 'arg_options' => array( 'sanitize_callback' => array( $this, 'check_user_password' ), ), ), 'capabilities' => array( 'description' => __( 'All capabilities assigned to the user.' ), 'type' => 'object', 'context' => array( 'edit' ), 'readonly' => true, ), 'extra_capabilities' => array( 'description' => __( 'Any extra capabilities assigned to the user.' ), 'type' => 'object', 'context' => array( 'edit' ), 'readonly' => true, ), ), ); if ( get_option( 'show_avatars' ) ) { $avatar_properties = array(); $avatar_sizes = rest_get_avatar_sizes(); foreach ( $avatar_sizes as $size ) { $avatar_properties[ $size ] = array( /* translators: %d: avatar image size in pixels */ 'description' => sprintf( __( 'Avatar URL with image size of %d pixels.' ), $size ), 'type' => 'string', 'format' => 'uri', 'context' => array( 'embed', 'view', 'edit' ), ); } $schema['properties']['avatar_urls'] = array( 'description' => __( 'Avatar URLs for the user.' ), 'type' => 'object', 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, 'properties' => $avatar_properties, ); } $schema['properties']['meta'] = $this->meta->get_field_schema(); return $this->add_additional_fields_schema( $schema ); } /** * Retrieves the query params for collections. * * @since 4.7.0 * * @return array Collection parameters. */ public function get_collection_params() { $query_params = parent::get_collection_params(); $query_params['context']['default'] = 'view'; $query_params['exclude'] = array( 'description' => __( 'Ensure result set excludes specific IDs.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'default' => array(), ); $query_params['include'] = array( 'description' => __( 'Limit result set to specific IDs.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'default' => array(), ); $query_params['offset'] = array( 'description' => __( 'Offset the result set by a specific number of items.' ), 'type' => 'integer', ); $query_params['order'] = array( 'default' => 'asc', 'description' => __( 'Order sort attribute ascending or descending.' ), 'enum' => array( 'asc', 'desc' ), 'type' => 'string', ); $query_params['orderby'] = array( 'default' => 'name', 'description' => __( 'Sort collection by object attribute.' ), 'enum' => array( 'id', 'include', 'name', 'registered_date', 'slug', 'include_slugs', 'email', 'url', ), 'type' => 'string', ); $query_params['slug'] = array( 'description' => __( 'Limit result set to users with one or more specific slugs.' ), 'type' => 'array', 'items' => array( 'type' => 'string', ), ); $query_params['roles'] = array( 'description' => __( 'Limit result set to users matching at least one specific role provided. Accepts csv list or single role.' ), 'type' => 'array', 'items' => array( 'type' => 'string', ), ); /** * Filter collection parameters for the users controller. * * This filter registers the collection parameter, but does not map the * collection parameter to an internal WP_User_Query parameter. Use the * `rest_user_query` filter to set WP_User_Query arguments. * * @since 4.7.0 * * @param array $query_params JSON Schema-formatted collection parameters. */ return apply_filters( 'rest_user_collection_params', $query_params ); } } /** * REST API: WP_REST_Settings_Controller class * * @package WordPress * @subpackage REST_API * @since 4.7.0 */ /** * Core class used to manage a site's settings via the REST API. * * @since 4.7.0 * * @see WP_REST_Controller */ class WP_REST_Settings_Controller extends WP_REST_Controller { /** * Constructor. * * @since 4.7.0 */ public function __construct() { $this->namespace = 'wp/v2'; $this->rest_base = 'settings'; } /** * Registers the routes for the objects of the controller. * * @since 4.7.0 * * @see register_rest_route() */ public function register_routes() { register_rest_route( $this->namespace, '/' . $this->rest_base, array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_item' ), 'args' => array(), 'permission_callback' => array( $this, 'get_item_permissions_check' ), ), array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'update_item' ), 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), 'permission_callback' => array( $this, 'get_item_permissions_check' ), ), 'schema' => array( $this, 'get_public_item_schema' ), ) ); } /** * Checks if a given request has access to read and manage settings. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return bool True if the request has read access for the item, otherwise false. */ public function get_item_permissions_check( $request ) { return current_user_can( 'manage_options' ); } /** * Retrieves the settings. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return array|WP_Error Array on success, or WP_Error object on failure. */ public function get_item( $request ) { $options = $this->get_registered_options(); $response = array(); foreach ( $options as $name => $args ) { /** * Filters the value of a setting recognized by the REST API. * * Allow hijacking the setting value and overriding the built-in behavior by returning a * non-null value. The returned value will be presented as the setting value instead. * * @since 4.7.0 * * @param mixed $result Value to use for the requested setting. Can be a scalar * matching the registered schema for the setting, or null to * follow the default get_option() behavior. * @param string $name Setting name (as shown in REST API responses). * @param array $args Arguments passed to register_setting() for this setting. */ $response[ $name ] = apply_filters( 'rest_pre_get_setting', null, $name, $args ); if ( is_null( $response[ $name ] ) ) { // Default to a null value as "null" in the response means "not set". $response[ $name ] = get_option( $args['option_name'], $args['schema']['default'] ); } /* * Because get_option() is lossy, we have to * cast values to the type they are registered with. */ $response[ $name ] = $this->prepare_value( $response[ $name ], $args['schema'] ); } return $response; } /** * Prepares a value for output based off a schema array. * * @since 4.7.0 * * @param mixed $value Value to prepare. * @param array $schema Schema to match. * @return mixed The prepared value. */ protected function prepare_value( $value, $schema ) { // If the value is not valid by the schema, set the value to null. Null // values are specifcally non-destructive so this will not cause overwriting // the current invalid value to null. if ( is_wp_error( rest_validate_value_from_schema( $value, $schema ) ) ) { return null; } return rest_sanitize_value_from_schema( $value, $schema ); } /** * Updates settings for the settings object. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return array|WP_Error Array on success, or error object on failure. */ public function update_item( $request ) { $options = $this->get_registered_options(); $params = $request->get_params(); foreach ( $options as $name => $args ) { if ( ! array_key_exists( $name, $params ) ) { continue; } /** * Filters whether to preempt a setting value update. * * Allows hijacking the setting update logic and overriding the built-in behavior by * returning true. * * @since 4.7.0 * * @param bool $result Whether to override the default behavior for updating the * value of a setting. * @param string $name Setting name (as shown in REST API responses). * @param mixed $value Updated setting value. * @param array $args Arguments passed to register_setting() for this setting. */ $updated = apply_filters( 'rest_pre_update_setting', false, $name, $request[ $name ], $args ); if ( $updated ) { continue; } /* * A null value for an option would have the same effect as * deleting the option from the database, and relying on the * default value. */ if ( is_null( $request[ $name ] ) ) { /* * A null value is returned in the response for any option * that has a non-scalar value. * * To protect clients from accidentally including the null * values from a response object in a request, we do not allow * options with values that don't pass validation to be updated to null. * Without this added protection a client could mistakenly * delete all options that have invalid values from the * database. */ if ( is_wp_error( rest_validate_value_from_schema( get_option( $args['option_name'], false ), $args['schema'] ) ) ) { return new WP_Error( 'rest_invalid_stored_value', sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ), array( 'status' => 500 ) ); } delete_option( $args['option_name'] ); } else { update_option( $args['option_name'], $request[ $name ] ); } } return $this->get_item( $request ); } /** * Retrieves all of the registered options for the Settings API. * * @since 4.7.0 * * @return array Array of registered options. */ protected function get_registered_options() { $rest_options = array(); foreach ( get_registered_settings() as $name => $args ) { if ( empty( $args['show_in_rest'] ) ) { continue; } $rest_args = array(); if ( is_array( $args['show_in_rest'] ) ) { $rest_args = $args['show_in_rest']; } $defaults = array( 'name' => ! empty( $rest_args['name'] ) ? $rest_args['name'] : $name, 'schema' => array(), ); $rest_args = array_merge( $defaults, $rest_args ); $default_schema = array( 'type' => empty( $args['type'] ) ? null : $args['type'], 'description' => empty( $args['description'] ) ? '' : $args['description'], 'default' => isset( $args['default'] ) ? $args['default'] : null, ); $rest_args['schema'] = array_merge( $default_schema, $rest_args['schema'] ); $rest_args['option_name'] = $name; // Skip over settings that don't have a defined type in the schema. if ( empty( $rest_args['schema']['type'] ) ) { continue; } /* * Whitelist the supported types for settings, as we don't want invalid types * to be updated with arbitrary values that we can't do decent sanitizing for. */ if ( ! in_array( $rest_args['schema']['type'], array( 'number', 'integer', 'string', 'boolean', 'array', 'object' ), true ) ) { continue; } $rest_args['schema'] = $this->set_additional_properties_to_false( $rest_args['schema'] ); $rest_options[ $rest_args['name'] ] = $rest_args; } return $rest_options; } /** * Retrieves the site setting schema, conforming to JSON Schema. * * @since 4.7.0 * * @return array Item schema data. */ public function get_item_schema() { $options = $this->get_registered_options(); $schema = array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'settings', 'type' => 'object', 'properties' => array(), ); foreach ( $options as $option_name => $option ) { $schema['properties'][ $option_name ] = $option['schema']; $schema['properties'][ $option_name ]['arg_options'] = array( 'sanitize_callback' => array( $this, 'sanitize_callback' ), ); } return $this->add_additional_fields_schema( $schema ); } /** * Custom sanitize callback used for all options to allow the use of 'null'. * * By default, the schema of settings will throw an error if a value is set to * `null` as it's not a valid value for something like "type => string". We * provide a wrapper sanitizer to whitelist the use of `null`. * * @since 4.7.0 * * @param mixed $value The value for the setting. * @param WP_REST_Request $request The request object. * @param string $param The parameter name. * @return mixed|WP_Error */ public function sanitize_callback( $value, $request, $param ) { if ( is_null( $value ) ) { return $value; } return rest_parse_request_arg( $value, $request, $param ); } /** * Recursively add additionalProperties = false to all objects in a schema. * * This is need to restrict properties of objects in settings values to only * registered items, as the REST API will allow additional properties by * default. * * @since 4.9.0 * * @param array $schema The schema array. * @return array */ protected function set_additional_properties_to_false( $schema ) { switch ( $schema['type'] ) { case 'object': foreach ( $schema['properties'] as $key => $child_schema ) { $schema['properties'][ $key ] = $this->set_additional_properties_to_false( $child_schema ); } $schema['additionalProperties'] = false; break; case 'array': $schema['items'] = $this->set_additional_properties_to_false( $schema['items'] ); break; } return $schema; } } Coal Mine | Coal Investor : Indonesian Coal Suppliers & Coal Mining

Coal Mine

admin

Thailand’s Need Of Coals

Thailand is one of the biggest coal consumers in the world. Even though there has been protests from the residents and activits for more than two years, Thailand will keep on with the planning to build coal-fired power plant. Even though there is opposition regarding to coal uses in Thailand, it’s hard just to remove coal from the list of efficient energy source because it really helps developing country like Thailand. Building coal-fired power plant means a lot for people. It can deliver electricity and performs industry well.

Thailand is going to build coal-fired power plant in a southern tourist province involving 800 megawatt. It’s included into Thailand’s Power Development Plan for 2015 to 2036. Therefore, Thailand will still continue using coal as the main ebergy source for the construction of power plants. The project itself had been on paused for about two years because there was opposition. However, Thailand has been firmed to continue the project since they think that it’s beneficial. It’s also safe and valuable to build coal-fired power plant.

It is predicted that the power plant will start generating power in 2021 if the construction begin in 2018. The main purpose for building coal-fired power plant is to provide electricity. As everyone knows that electricity is one of the main important role for living whether you are living in modern city or rural areas. Electricity is essential because you can anything with it. You can get a job and money. Both for daily living to industrial activities, electricity is crucial element.

So why coal is still preferred by many countries despite of many protests ?

a.The availability of coal is more stable than other energy resources like oil or natural gas. People also realize that the world’s oil reserve is decreasing. We will reach to the point where there is no oil anymore that can be use as energy source. Meanwhile, coal still has enough reserve for years to come which can cover the needs of energy source worldwide.

b.The next reason is the price. Coal has lower price than other energy resources. Thus, it helps developing countries to grow without having much difficulty with budget. Coal is affordable for many countries in the world, especially Asia and Afrika. Economy has become the main issue on why many countries still depend on coals despite of the protests.

c.It’s not hard to get coal since it’s widely spread throughout the world. There are many places filled with coals. Even though a country doesn’t have coal mining site, they can easily import it from other countries. Besides, there won’t be any sudden scarcity to coals.

d.Coal mining industry employ many people around the world since the process of mining the coal are divided into several stages. It opens the opportunity for people to develop their life. From the process of coal mining to distributing, it involves many employee which depend their lives on coal mining industry. Thus, it’s hard to resist coals as the most effective energy source.

Furthermore, Thailand will continue building coal-fired power plant to solve electricity demand. Thus, Thailand needs to import coals from its neighbor like Indonesia. Indonesia has large coal reserves which can easily export their coal to another country. Coal Investors is one of coal mining companies from Indonesia, located in South Kalimantan.

Coal Investors own their own coal mines in South Kalimantan. Thus, coals are mined and distributed from the site. If you are interested to buy coals from Coal Investors, you can contact the company or visit it directly to see coal mining process. Coal Investors is coal mining company available for long-term contract as what client wants.

admin

Philippines Needs Imported Coals

Philippines currently has issued about renewable energy plants and the use of coal-fired plants. Coal is still the major energy source for Asian countries. Its affordable price and stable availability makes coal continue to be needed by many developing countries regardless the environmental issues. It’s possible that someday there will be renewable energies which can replace the role of coal. However, it’s not today. It’s still hard for renewable enegies to compete with cheap coal.

Philippines indeed has develop renewable energy resources by installing 1,000 MW as of April 2016. However, it’s not the end of the story. New coal and natural gas plants built have much higher capacities indeed. They have reduced renewable energy’s share in the power mix. It proves how hard it is to develop renewable energy sources. Meanwhile, Philippines currently has 17 operating coal plants. Indeed, 29 plants are in the pipeline.

The number of coal plants are higher than natural gas. It proves that Philippines still needs coal as the primary energy source to fulfill their needs. The reasons why Philippines will continue using coal as the main energy source are simple.
• Philippines has one of the highest electricity rates in the world. Increasing power rates will lead to strong resistance from end-users as well as politicians and society organization. Using more expensive energy sources will increase the rates which can lead to chaos.
• Coal is a secire investment providing continuity in revenuing streams. Coal projects are less risky than renewable energy projects. The renewable energy resources fluctuate widely every year, that’s what make it too risky.
• Philippine’s financing institutions are more familiar with coal plant development. Thus, it will make them easier in managing the construction and operations. Meanwhile, Philippines still lacks of experience in developing renewable energy sources. It will make them rely on foreign contractors. In the end, it will cause excessive spending. The project of renewable energy costs a lot higher compare to other countries whose technologies have already in advanced level.

The issue about environmental damage caused by coal is heated. However, finding out the right solution to replace coal is also still in the process. Thus, most developing countries still need coal as their main energy sources. Philippines also has shown initiative and effort in developing renewable energy project. However, it’s not easy to maintain and do further development due to lack of technologies and high cost. Philippines rely on imported coals from its neighbor like Indonesia.

Being a great partner in coal supplying with Indonesia is advantageous. Both are located near to each other, making it more efficient in the process of delivering coal supply. It also won’t increase the expense of transportation. In addition, Indonesia also has many coal mining companies. Indonesia has many coal mining sites owned by government and independent companies. If you are interested to buy coal from Indonesia, you need to find reliable coal mining company first.

Coal Investors is one of the most trusted and reliablr coal mining company from Indonesia. It’s located in South Kalimantan. The coal mining site is owned by Coal Investors that you can even visit the site if you want to survey the location and the process of coal mining. Coal Investors is a great option if you want a reliable supplier. You can go for short or long-term contract. The price of coal mined by Coal Investors is competitive. However, you don’t need to doubt its quality coal. Coal Investors always opens hand for your visit anytime. However, make sure you make an appointment before visiting. Contact Coal Investors now to get more detailed information about coal suppying procedures.

admin

Coals Demand In Cambodia

Coal has been a source of economic value in the world. Coal mining industry contributed to the development of economy worldwide. In addition, coal also plays major role as a source of employment. It was the third largest employer of the total mining workforce. Indeed, it keeps rising. The most important of all is the role of coal as the source of energy. Coal is the world’s dominant energy source. Electricity is being produced by the help of coal as it’s fuel.

To produce electricity, mined coal is delivered to coal-fired power plants. Then, the electricity is generated. The coal play important role in producing electricity. In the process, coal is combusted to boil water and then produce steam to operate a conventional steam turbine as well as generator. As the result, there is electricity that can be used for everyone who needs it. Cambodia is a country with growing power generation. The country even still imports electricity. The issue about future of energy generation in Cambodia is still in discuss.

A country like Cambodia is in an immediate need to produce electricity. However, infrastructure also requires expensive spending. Thus, Cambodia needs to balance between producing electricity at los cost to be able maintain and developing infrastructure. Coal is energy sources which can be a great solution. Electricity access is still hard to be delivered to everyone in Cambodia. The access is still limited so the process of developing electricity generation is in demand.

It seems that Cambodia will still need to import coal for its neghbor like Indonesia to fulfill their needs of energy source. That’s the way to solve problem in Cambodia. Coal is very important for Cambodia and it will continue to be important. However, Cambodia also needs to find the right coal technologies in order coal can be more efficiently consumed without harming the environment so it won’t lead to another problem.

It’s important to ensure that electricity transmission in Cambodia is efficient. For Cambodia, having stable grid which can handle intermittencies should comes before trying to have big renewable component. Energy flow should be balanced and maintained in a proper way so the needs of electricity in Cambodia can be fulfilled. Therefore, all people in Cambodia will be able to use electricity for their daily needs.

The future of power generation in Cambodia is predicted to stay at coal as the main source. It’s followed by a note on proper environmental management. Cambodia needs of coal is expected to benefits coal-fired power plants to produce electricity thoroughly to every region. The vision that Cambodia has is to deliver affordable electricity. Therefore, electricity distribution can be more even.

Cambodia currently has two coal-fired power plants. They are located in Preah Sihanouk province. Both has different owner. The one partially owned by Lao Meng Khin’s, Cambodian People’s Party Senator. Another is owned by Malaysian-owned Leader Universal Holdings. Coal will continue to be the main power asset in Cambodia. The reason is simple, coal is cheap. In addition, Cambodia will also have further coal projects in the future. Cambodia has a plan to build another power plant as part of energy production to provide electricity.

Cambodia’s main coal exporter is Indonesia, its neighbor. Indonesia is one of the largest coal producing in the world. Cambodia is also one of destination for Indonesia to export coal. There are many coal mining companies in Indonesia, and one of the most reliable one is Coal Investors. It’s coal mining company located in South Kalimantan and have their own coal mining sites. You can visit directly to the site to survey coal mining process and making a deal.

admin

Japan To Build More Coal-Fired Power Plants

Domestic coal production in Japan has come to an end since 2002. Since then, Japan relies on imports. It was estimated that up till 2012, Japan have importes about 186 million tonnes of coals. 133 millions tonnes are thermal coal and 43 millions tonnes are metallurgical coal. Japan imports coal mostly from Australia. The Government of Australia stated that Japan currently has slight decrease in thermal coal consumption to 2018 but there is also sligh increase in metallurgical coal consumption.

Japan has about 243 GW of installed electrical generating capacity coming mostly fired by coal then oil or gas. As of mid-2012, there are 61 thermal power plants in Japan. In addition, Japan still build other 6 power plants which 3 of them are using coal for generation. In 2010, coal accounts for 25% of electricity generation in Japan. Here are some partly and wholly coal-fired power stations owned by Japan :

a.Tomato-Atsuma Power Station
b.Haramachi Power Station
c.Noshiro Power Station
d.Hirono Thermal Power Station
e.Hitachinaka Thermal Power Station
f.Hekinan Power Station, etc

When there was an earthquake in Japan, it damaged some of coal-fired power plants. However, it didn’t lead to an increase in coal consumption. For Japan, coal-fired generation has always been a base load. Japan will seem to continue expanding coal-fired power plants to meet energy demand especially for electricity. However, Japan also has intention to reduce fuel costs by building new plants that will be designed for lower grade coals. Japan as a country with excellent technologies is encourage to develop clean coal tehnologies.

Japan shows great support for fossil fuel use, saying that it helps developing countries adopt the best available technologies for coal-fired power plants. Japan is considered as the biggest providers of coal financing. Japan says that it’s beneficial to develop more efficient coal-fired plants as it will cut carbon dioxide emissions. For developing countries, it will be beneficial and helpful to improve energy security by relying on cheal fuels like coal.

Japan said that it’s not realistic to quit coal entirely as growing power in high demand. In fact, India and Indonesia already planned to add more coal capacity to meet the needs of efficient energy source in many countries all over the world. Japan with their project to create more efficient coal-fired power plants is expected to help many developing countries in their struggles with power issues.

Technologies found by Japan is expected to push for energy-related insfrastructure. Therefore, thermal power plants will have high-efficiency and it can help removing air pollutant or at least reducing it. Cheap electricity is the main goal on Japanese project of more-efficient coal-fired power plants. In emerging economies, power is in a high demand. It’s not only in Asia but Africa as well.

Japan will continue importing coals from other countries to meet their needs in building power plants. Even though Australia is the biggest supplier of coal for Japan, seeing the increasing needs of coals makes it possible for Japan to import coal for another country like Indonesia. Indonesia is one of the largest coal producers in the world. Thus, importing coals from Indonesia can be beneficial for both countries.

In Indonesia, there is Coal Investors, a coal mining company located in South Kalimantan. It is reliable coal supplier which always open hands for partnership in coal supplying. Having their own coal mines, Coal Investors is ready to sign for long-term contract. If you are interested to import coals from Coal Investors, just contact or visit the company directly. You’ll be welcomed to visit the coal mine sites to survey the location of coal mining process.

admin

Current Coal Needs In Taiwan

Taiwan’s energy is 98 % imported. Taiwan have been struggling to develop sustainable, clean, and independent energy as they lack energy resources. The high demand for imported energy resources can’t be denied. Taiwan use oil as their energy source for about 48.5% of the total accounts. Meanwhile, coal comes next with 29.2%. They produce electricity mostly from fossil fuels, wind, nuclear, and also hydro power. Aside from it, Taiwan is still busy building their industries to develop their country. The need of energy resource is in high demand.

Taiwan received 65.96 million tons of coal import in 2013. It consisted of 58.96 million tons of steam coal and 7.02 million tons of cooking coal. Indonesia is the largest coal exporter country to Taiwan. Indonesia and Taiwan has been joing hand for coal supply for many years. The location of both countries are close to each other. No wonder that this kind of export-import partership can be advantageous for both countries. Taiwan is in high demand for coal supply as they are still developing their country. Meanwhile, Indonesia have plentiful energy resources like coals which can be exported to fulfill other countries needs.

Coal is useful energy resource used to produce energy both in a form of heat and electricity. To generate electricity, a country needs powerful and effective energy source. Coal is one of the most used energy resources in the world. It is preferred because it offers lower price than others. Besides, availability of coal is more secured, unlike oil or natural gas.

Taiwan has been implementing the principal about energy management to assure stability of energy supply. However, totally replacing coals with renewable energy sources cannot be done in an instant. Thus, Taiwan still need to import coals from other countries like Indonesia to ensure the stability of their energy supply. Furthermore, Taiwan is also trying hard to accelerating the rationalization of energy pricing. Energy efficient is the main issue for all countries in the world. However, coal cannot be removed from the list when it comes to price.

Coal offers more affordable price comparing to other energy sources. Taiwan’s effort in balancing energy pricing and cost can be optimized by choosing coals rather than oil or gas. Steady supply of coals can be assured since there won’t be any sudden scarcity of coals, unlike oild and natural gas. The development of regulations and policies regarding to energy comission in Taiwan is still going on. Thus, the use of coal as one of the main energy source in Taiwan is also still running.

Taiwan has also promising land that is expected to be filled with energy resources. However, the development is still vulnerable and it’s still under tight research. Until the time comes when Taiwan can be more independent to use their own energy sources gained from their own land, Taiwan still needs to import energy sources from other countries. For coal, Taiwan will still rely on Indonesia as the main supplier.

Furthermore, if you’re in need of coal supplier, you can rely on Indonesian coal mining company like Coal Investors. It is coal mining company located at South Kalimantan. The company has its own coal mine sites in Kalimantan so the coal that is going to be exported is fresh from mines. Coal Investors is reliable supplier, ready for partnering in coal supply to another country. Coal Investors always opens hands if you want to ask anything regarding to call supply. You can also directly visit the company and its coal mining site to see the process of coal mining. A friendly visit is always welcomed for advantageous partnership.

admin

Malaysia Needs Coals For Electricity Generation

Malaysia has coal mining sector operating in several sites. Most of them are used or consumed by power generating plants and the remaining supply goes to cement, iron, and steel sectors. Malaysia tries to push the development of some region. However, the development requires electricity. Energy demand in Malaysia is rising. It is even set to use 40 million tonnes of coal a year by 2020. Malaysia in in their momentum of economy. Thus, it pushes up energy demand which keeps on rising year by year.

It is known that about 45% of Nalaysian peninsula’s energy supply comes from coal. Indeed, it’s going to increase in the following years. Malaysia also uses natural gas as their energy resources. However, it keeps depleting and Malaysia needs steady supply of energy source. Malaysia alsa has a plan to develop a modern power system with smart and sustainable concept. However, that type of transformation cannot be done in an instant. It needs long process and requires much money. Malaysia is now focusing on delivering only the most high-efficiency power plants.

Until now, Malaysian power plant imports tons of coals from Indonesia. Even though Malaysia has their own coal mining sites, they are not as large as Indonesia’s. Thus, it can’t fulfill high demand of coal for their power plants. As of 2017, Malaysia imports 10 million tons of coal from Indonesia. Malaysia has steam power plant with installed capacity of 3.100 MW. It needs 10 million tons of coal supply per year. It must be hard for Malaysia alone to fulfill the needs. Thus, importing coal from Indonesia is the best solution. Besides, Indonesia is their neighbor so the partnership is benefiting each other.

To install 3.100 MW capacity, it needs four units of power generators. Thus, coal is in high demand. Coal imported from Indonesia usually delivered by ships. The coals then being stored in Manjung coal terminal. Malaysia has signed contract with several distributors from Indonesia. Coal purchase contract signed by Malaysia lasts from three to five years in general.

There are reasons why coal is preferred as the main energy resources all over the world, such as :

a.The availability of coal is more stable than other energy resources like oil or natural gas. People also realize that the world’s oil reserve is decreasing. In addition, renewable energy is still in the process of development and not all countries in the world can do it since it requires high budget.

b.Coal has lower price than other energy resources. Thus, it helps developing countries to proceed development in many sectors without having much difficulty with budget. Coal is affordable for many countries in the world, especially Asia and Afrika. Economy is critical for many all countries. That’s why many countries still depend on coals.

c.It’s not hard to get coal since it’s widely spread throughout the world. There are many places filled with coals especially in U.S and Asia. Thus, there won’t be any sudden scarcity to coals.

Furthermore, Malaysia will continue building coal-fired power plant to fulfill electricity demand. Thus, Malaysia needs to import coals from its neighbor like Indonesia. Indonesia has large coal reserves which can easily export their coal to another country. Coal Investors is one of coal mining companies from Indonesia, located in South Kalimantan.

Coal Investors own their own coal mines in South Kalimantan. Thus, coals are mined and distributed from the site. If you are interested to buy coals from Coal Investors, you can contact the company or visit it directly to see coal mining process. Coal Investors is coal mining company available for long-term contract as what client wants.

admin

Vietnam Needs Of Coals

Coal is a plentiful resource used to produce energy. It has been used all over the world both in a form of electricity and heat. Even though some people think that coal is all the same, however it is a complex resource. It has varied composition even within the same deposit. Thus, each different coal is used for different purpose. Generally, coal is a useful energy resource which can help to our living. There are other types of energy resources other than coal but it’s one of the most sought amongst them. It is the cheapest source of energy and it also provides standle source of energy. Thus, even though there are some arguments about its impact to the environment, it’s still hard to replace coal with other energy sources.

There are many countries in the world depending on coal as their primary energy resource. Vietname is one those countries who rely on coal for their energy source especially for electricity. There are reason why coal is needed the most such as:

a.As told above that coal is way cheaper than other energy resources. Thus, for developing country like Vietnam, coal can be a solution for economical issue. A country cannot just give up on using energy resources just because they are not affordable. Thus, they need to find affordable energy source like coal. Vietnam have been using coals for years as their main energy source. It proves that coal is needed the most by developing country due to its low-price.

b.Coal provides more stable energy compare to others. There won’t be any sudden scarcity like natural gas. It doesn’t mean that coal will never be running out of stocks. However, it’s stability is ensured for a long period time ahead so there is no need to worry. Vietnam as a developing country need continuity in coal supply for their needs like building infrastructure, industrial, and other sectors.

Coal is irresistably needed by many developing countries. Even though there are calls to decrease the use of coal worldwide, the deman of coal is still high. To replace such important energy resource like coal means that the substitution should be there already. Thus, if the substitution can’t even be there yet, how come coal use can be decreased. Coal is considered as a source of economic value in many countries, included Vietnam.

Vietnam has electricity generated from coal-fired therman power plant by the accounts of 50%. The total power of this country mainly depends on coal. The use of renewable sources is still at the very low level. Thus, Vietnam still need coals as the primary energy sources. However, Vietnam cannot fulfill their needs of coals thoroughly due to lack of coal reserves. They need to import coal from other countries like Indonesia for coal supply.

Vietnam uses coal-fired themal power plant because it’s still the major role in generating electricity in this country. Like it or not, Vietnam needs to be dependant on coals. Thermal power plants needs to import coal to meet demand. Joining partnership for coal importing with Indonesian coal mining company can be advantageous though. Vietnam and Indonesia are located closely to each other. The budget for transportation or delivery process won’t be too high.

Furthermore, one of the most trusted and reliable coal mining company from Indonesia is Coal Investors who are available for coal supply partnership. Coal Investors are always ready for long-term contract in supplying coal to another country. Coal Investors own their coal mining site in South Kalimantan. Thus, buyers can make a direct call or visit the site to do a survey before making a deal.

admin

The Need Of Coals In India

India is one of destination point for coal export by Indonesia. The needs of coals in India is still increasing as the country still building infrastructure generally in many regions. Coal is the most reliable energy source for India. Meanwhile, India itself cannot fulfill coal demand thoroughly since their coal reserve isn’t enough.

The comodity of coal in India is high indeed. India’s coal production was about 605 million tons. India is in the list of top three for coal production, meanwhile Indonesia is at the fourth place. However, India still relies on imported coals and Indonesia is one of the most valuable partner for coal export-import. Indonesia as one of the largest coal exporters can fulfill coal needs in India for sure. India itself consumed 8% of the total world’s coal. Thus, it automatically makes India as the third largest consumer as well. India imported 160 millions of coals which are used mostly for electricity generator.

Asian countries like India, Pakistan, Philipine still rely on Indonesia for coal supply. Indeed, Pakistan and Philipine have stated that they are ready to add imported coals portion for the years 2017 and the following years. Indonesia has enough coal reserves to be exported to other countries even for long-term supply.

What India needs the most is steam coal. Even though India is in the top list for coal production, in fact they still rely on Indonesia’s supply. It’s shown by the raising of coal demand every year. In 2014, Indonesia exported 34,78 tons of steam coals to India to fulfill their needs. Coal is indeed one of the most reliable energy sources in the world. It has many benefits such as affordable price and also its availability.

If you need the most reliable coal mining companies from Indonesia, there is Coal Investors. It’s coal mining company which has good reputation in coal supply to many countries. To fulfill your needs of coal supply, Coal Investors is trusted and reliable, since it works professionally in coal export. There are many reasons why you should choose Coal Investors :

a.Coal Investors can supply coals in stable mode for regular routine. It’s because Coal Investor has their own coal mines located in South Kalimantan, Indonesia. Coal reserve owned by Coal Investors will be able to fulfill every client’s needs. In addition, mining process is directly done in the location and the coals will be exported directly from the site. Thus, you will be supplied with quality coal fresh from mines.

b.Coal Investors offers affordable and competitive prices for coal supply. The price of coals worldwide is up and down. However, Coal Investors ensures you that the price will be very competitive.

c.Coal Investors is open for both short-term or long-term contract in supplying coals. The process of coal supplying will be done based on contract agreed by both parties. As told above that client’s needs is priority. Hence contract will be clearly made and transparent to make both parties gain benefits from the valuable partnership.

There are many coal mining companies in the world. However, Indonesia is one of the most active coal-supplier in the world. Besides, Indonesia has Coal Investors as one of the most reliable mining companies. If you are looking for reliable coal supplier, you can directly contact Coal Investors to get more detailed information about coal supplying process. You can also directly visit coal mining site of Coal Investors in South Kalimantan, Indonesia. Thus, you can take a look at coal mining process. You can decide yourself whether coals from Coal Investors are qualified to meet your needs or not.

admin

Sri Lanka Imported Coals Consumption

Sri Lanka is considering coal power plants to meet its spiralling energy needs. The country was reliant to coal imports and started to consider clean energy. However, it cannot quit coal just entirely because they have high demand to meet growing. Small countries in the world are actually facing the same dilemma. To fuel their surging economic growth, it leads to the increasing amounts of energy as well. On the other hand, they lack of natural energy resources to generate energy themselve which make the problem is more complicated and dilemmatic.

However, Sri Lanka is a bit different from other small countries. It can turn the dilemma to become a quite successful strategy. Sri Lanka uses solar energy for homes and coal for industry. Thus, Sri Lanka will continue developing clean energy but still imports coals. In remote regions in Sri Lanka, electricity is not widely spread. Thus, Sri Lanka needs to continue building electricity generation to meet high demand in electricity distribution.

Sri Lanka has developing clean and sustainable sources of energy to meed their needs. However, coal cannot be cut entirely since the energy needs is too huge to be covered only by solar or other green energies. Even though coal is considered as one of the most polluting sources of electricity generation, it still plays major role in providing needs of power in the country, especially in small country like Sri Lanka.

Sri Lanka has a coal-fired power plant names The Norocholai Power Station. It generates more energy then any other facility there. In fact, Sri Lanka plans to build another coal-fired power plant on the island’s east coast. It’s planned to be the last coal-fired power plant to ever built by the government due to its mission to develop clean energy sources.

Sri Lanka relis on coal imports since it doesn’t have its own coal resources. China is important role in building up and constructing the country’s coal-fired plant as well as energy capacity. However, the second plant is planned to be built with the help from India. However, Sri Lanka imports coals from Indonesia as the main provider for coal supply. Sri Lanka depends on fossil fuels like coal as the main energy source since the price of oil keeps increasing.

The global demand of coal is high that importing coals from world’s biggest coal exporters can help. Sri Lanka also doesn’t have anu coal reserves so coal imports is still the first option to choose. The one existing coal power station in Sri Lanka has been running for six years and it will continue to run throughout the next two decades. Coal is considered to be cheap energy source which can meet electricity demand as well as increase quality of life for the citizens at lower cost.

There are many coal mining companies in the world that can export coals to Sri Lanka. However, Sri Lanks has neighbor with large coal production, Indonesia. Importing coals from Indonesia can be advantageous since it won’t require high cost for delivering process. Indonesia is one of the largest coal exporters in the world.

One of the most reliable mining company from Indonesia which won’t make you regret for having a partnership is Coal Investors. If you are looking for reliable coal supplier, you can directly contact Coal Investors for having further details about the process of coal supplying and contract. You can also directly visit the coal mining site of Coal Investors in South Kalimantan, Indonesia. Go and take a look at how the company do the coal mining process by yourself. You will see the quality of coals to be supplied to other countries.

admin

Bangladesh Needs More Imported Coals

Bangladesh has put interest in strengthening partnership with Indonesia especially in export and import. Bangladesh also needs imported coals from Indonesia since their energy supply is in demand. Indonesia as one of the largest producers of coals must be feeling great to see that Bangladesh has interest to do economical partnership in energy supply.

Bangladesh is still developing their country in many sectors included industrial sector. To fulfill the needs of energy supply, Bangladesh relies on imported coals since they can’t rely on their coal reserves alone. By joining partnership with Indonesia, Bangladesh has gained benefits. Indonesia is included into top ten list for coal reserves. Indonesia itself has relied on coal as the main energy supply for power plant, and other sectors. However, Indonesia has potential land with coals to be mined. Thus, Indonesia has still much of coal reserves to be exported to other countries who really need coals supply.

With friendly relationship between Bangladesh and Indonesia, it’s even beneficial to do export-import of coals. Bangladesh is still building power plants here and there so the needs of energy supply like coals in increased. Meanwhile, Indonesia has coal reserves which will be enough to fulfill Bangladesh’s needs in coals.

Indonesia has many promising coal mining companies especially because Indonesia has valuable coal mines in many places. However, it’s important to choose reliable company since coal supply should be done with the right procedure involving much money. Being selective in choosing coal mining company is essential for any buyers. Aside from it, type of contract should be chosen wisely, whether it’s short-term or long-term contract of coal supplying. However, long-term contract can be beneficial if you need continued coal supply so you don’t need to keep changing partnership.

One of the most reliable coal mining companies in Indonesia is Coal Investors. It’s coal mining company with good reputation in making client’s needs as priority. To fulfill your needs of coal supply, you can rely on Coal Investors, since it works professionally in coal export. These are reasons why you should choose Coal Investors:

a.Coal Investors offers affordable and competitive prices of coals. The price of coals is up and down. However, Coal Investors ensure you that the price will be very competitive. Thus, you still can afford to buy coals from Coal Investors as needed.

b.Coal supply in Coal Investors is stable and there is won’t be any running out of coals case. Coal Investors has their own coal mines located in South Kalimantan, Indonesia. Coal supply will be able to fulfill every client’s needs. The mining process is directly done in the location and the coals will be exported directly from the site. Quality coal is fresh from mines.

c.Coal Investors is open either for short or long-term contract to supply coals. Everything needed for coal supplying will be delivered through clear and beneficial contract. As told above that client’s needs is priority. Hence contract will be as clear as the ice to make both parties gain benefits from the partnership.

There are many coal mining companies in the world. However, Coal Investors is one of the most reliable mining company which won’t make you regret for having a partnership. If you are looking for reliable coal supplier, you can directly contact Coal Investors for having further details about the process of coal supplying. Or, you can directly visit the coal mining site of Coal Investors in South Kalimantan, Indonesia, to take a look at how the company do the coal mining process and to see the quality of coals to be supplied to other countries. Coal Investors always open hands for a visit.