LLMS_REST_Memberships_Controller
Source Source
File: libraries/lifterlms-rest/includes/server/class-llms-rest-memberships-controller.php
class LLMS_REST_Memberships_Controller extends LLMS_REST_Posts_Controller { /** * Enrollments controller. * * @var LLMS_REST_Enrollments_Controller */ protected $enrollments_controller; /** * Post type. * * @var string */ protected $post_type = 'llms_membership'; /** * Route base. * * @var string */ protected $rest_base = 'memberships'; /** * Additional rest field names to skip (added via `register_rest_field()`). * * @var string[] */ protected $disallowed_additional_fields = array( 'visibility', // It maps to `catalog_visibility` in the resource schema. ); /** * Constructor. * * @since 1.0.0-beta.9 * @since 1.0.0-beta.27 Call parent constructor. * * @return void */ public function __construct() { parent::__construct(); $this->enrollments_controller = new LLMS_REST_Enrollments_Controller(); $this->enrollments_controller->set_collection_params( $this->get_enrollments_collection_params() ); } /** * Retrieves the query params for the enrollments objects collection. * * @since 1.0.0-beta.9 * * @return array Collection parameters. */ public function get_enrollments_collection_params() { $query_params = $this->enrollments_controller->get_collection_params(); unset( $query_params['post'] ); $query_params['student'] = array( 'description' => __( 'Limit results to a specific student or a list of students. Accepts a single student id or a comma separated list of student ids.', 'lifterlms' ), 'type' => 'string', 'validate_callback' => 'rest_validate_request_arg', ); return $query_params; } /** * Get action/filters to be removed before preparing the item for response. * * @since 1.0.0-beta.9 * * @param LLMS_Membership $membership Membership object. * @return array Array of action/filters to be removed for response. */ protected function get_filters_to_be_removed_for_response( $membership ) { $filters = array(); if ( llms_blocks_is_post_migrated( $membership->get( 'id' ) ) ) { $filters = array( // hook => [callback, priority]. 'lifterlms_single_membership_after_summary' => array( // Membership Information. array( 'callback' => 'lifterlms_template_pricing_table', 'priority' => 10, ), ), ); } /** * Modify the array of filters to be removed before building the response. * * @since 1.0.0-beta.9 * * @param array $filters Array of filters to be removed. * @param LLMS_Membership $membership Membership object. */ return apply_filters( 'llms_rest_llms_membership_filters_removed_for_response', $filters, $membership ); } /** * Get the Membership's schema, conforming to JSON Schema. * * @since 1.0.0-beta.27 * * @return array */ protected function get_item_schema_base() { $schema = (array) parent::get_item_schema_base(); $schema['properties']['auto_enroll'] = array( 'description' => __( 'List of courses to automatically enroll students into when they\'re enrolled into the membership.', 'lifterlms' ), 'type' => 'array', 'default' => array(), 'items' => array( 'type' => 'integer', ), ); $schema['properties']['catalog_visibility'] = array( 'description' => __( 'Visibility of the membership in catalogs and search results.', 'lifterlms' ), 'type' => 'string', 'enum' => array_keys( llms_get_product_visibility_options() ), 'default' => 'catalog_search', 'context' => array( 'view', 'edit' ), ); $schema['properties']['categories'] = array( 'description' => __( 'List of membership categories.', 'lifterlms' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'context' => array( 'view', 'edit' ), ); $schema['properties']['instructors'] = array( 'description' => __( 'List of post instructors. Defaults to current user when creating a new post.', 'lifterlms' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'arg_options' => array( 'validate_callback' => 'llms_validate_instructors', ), 'context' => array( 'view', 'edit' ), ); $schema['properties']['restriction_action'] = array( 'description' => __( 'Determines the action to take when content restricted by the membership is accessed by a non-member. - `none`: Remain on page and display the message `restriction_message`. - `membership`: Redirect to the membership\'s permalink. - `page`: Redirect to the permalink of the page identified by `restriction_page_id`. - `custom`: Redirect to the URL identified by `restriction_url`.', 'lifterlms' ), 'type' => 'string', 'default' => 'none', 'enum' => array( 'none', 'membership', 'page', 'custom' ), 'context' => array( 'view', 'edit' ), ); $schema['properties']['restriction_message'] = array( 'description' => __( 'Message to display to non-members after a `restriction_action` redirect. When `restriction_action` is `none` replaces the page content with this message.', 'lifterlms' ), 'type' => 'object', 'context' => array( 'view', 'edit' ), 'arg_options' => array( 'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database(). 'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database(). ), 'properties' => array( 'raw' => array( 'description' => __( 'Raw message content.', 'lifterlms' ), 'type' => 'string', 'context' => array( 'edit' ), ), 'rendered' => array( 'description' => __( 'Rendered message content.', 'lifterlms' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), ), 'default' => __( 'You must belong to the [lifterlms_membership_link id="{{membership_id}}"] membership to access this content.', 'lifterlms' ), ); $schema['properties']['restriction_page_id'] = array( 'description' => __( 'WordPress page ID used for redirecting non-members when `restriction_action` is `page`.', 'lifterlms' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), 'arg_options' => array( 'sanitize_callback' => 'absint', ), ); $schema['properties']['restriction_url'] = array( 'description' => __( 'URL used for redirecting non-members when `restriction_action` is `custom`.', 'lifterlms' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'format' => 'uri', 'arg_options' => array( 'sanitize_callback' => 'esc_url_raw', ), ); $schema['properties']['sales_page_page_id'] = array( 'description' => __( 'The WordPress page ID of the sales page. Required when `sales_page_type` equals `page`. Only returned when the `sales_page_type` equals `page`.', 'lifterlms' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), 'arg_options' => array( 'sanitize_callback' => 'absint', ), ); $schema['properties']['sales_page_type'] = array( 'description' => __( 'Defines alternate content displayed to visitors and non-enrolled students when accessing the post. - `none` displays the post content. - `content` displays alternate content from the `excerpt` property. - `page` redirects to the WordPress page defined in `content_page_id`. - `url` redirects to the URL defined in `content_page_url`.', 'lifterlms' ), 'type' => 'string', 'default' => 'none', 'enum' => array_keys( llms_get_sales_page_types() ), 'context' => array( 'view', 'edit' ), ); $schema['properties']['sales_page_url'] = array( 'description' => __( 'The URL of the sales page content. Required when `sales_page_type` equals `url`. Only returned when the `sales_page_type` equals `url`.', 'lifterlms' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'format' => 'uri', 'arg_options' => array( 'sanitize_callback' => 'esc_url_raw', ), ); $schema['properties']['tags'] = array( 'description' => __( 'List of membership tags.', 'lifterlms' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'context' => array( 'view', 'edit' ), ); /** * Filter item schema for the membership controller. * * @since 1.0.0-beta.9 * @deprecated 1.0.0-beta.27 * * @param array $schema Item schema data. */ return apply_filters_deprecated( 'llms_rest_membership_item_schema', array( $schema, ), '[version]', "llms_rest_{$this->get_object_type( $schema )}_item_schema" ); } /** * Maps a taxonomy name to the relative rest base. * * @since 1.0.0-beta.9 * * @param object $taxonomy The taxonomy object. * @return string The taxonomy rest base. */ protected function get_taxonomy_rest_base( $taxonomy ) { $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; $taxonomy_base_map = array( 'membership_cat' => 'categories', 'membership_tag' => 'tags', ); return isset( $taxonomy_base_map[ $base ] ) ? $taxonomy_base_map[ $base ] : $base; } /** * Prepares a single post for create or update. * * @since 1.0.0-beta.9 * * @param WP_REST_Request $request Request object. * @return array|WP_Error Array of llms post args or WP_Error. */ protected function prepare_item_for_database( $request ) { $prepared_item = parent::prepare_item_for_database( $request ); $schema = $this->get_item_schema(); // Restriction action. if ( ! empty( $schema['properties']['restriction_action'] ) && isset( $request['restriction_action'] ) ) { $prepared_item['restriction_redirect_type'] = $request['restriction_action']; } // Restriction page id. if ( ! empty( $schema['properties']['restriction_page_id'] ) && isset( $request['restriction_page_id'] ) ) { $page = get_post( $request['restriction_page_id'] ); if ( $page && is_a( $page, 'WP_Post' ) ) { $prepared_item['redirect_page_id'] = $request['restriction_page_id']; } else { $prepared_item['redirect_page_id'] = 0; } } // Restriction URL. if ( ! empty( $schema['properties']['restriction_url'] ) && isset( $request['restriction_url'] ) ) { $prepared_item['redirect_custom_url'] = $request['restriction_url']; } // Sales page id. if ( ! empty( $schema['properties']['sales_page_page_id'] ) && isset( $request['sales_page_page_id'] ) ) { $page = get_post( $request['sales_page_page_id'] ); if ( $page && is_a( $page, 'WP_Post' ) ) { $prepared_item['sales_page_content_page_id'] = $request['sales_page_page_id']; } else { $prepared_item['sales_page_content_page_id'] = 0; } } // Sales page type. if ( ! empty( $schema['properties']['sales_page_type'] ) && isset( $request['sales_page_type'] ) ) { $prepared_item['sales_page_content_type'] = $request['sales_page_type']; } // Sales page URL. if ( ! empty( $schema['properties']['sales_page_url'] ) && isset( $request['sales_page_url'] ) ) { $prepared_item['sales_page_content_url'] = $request['sales_page_url']; } /** * Filters the membership data for a response. * * @since 1.0.0-beta.9 * * @param array $prepared_item Array of membership item properties prepared for database. * @param WP_REST_Request $request Full details about the request. * @param array $schema The item schema. */ $prepared_item = apply_filters( 'llms_rest_pre_insert_membership', $prepared_item, $request, $schema ); return $prepared_item; } /** * Prepare links for the request. * * @since 1.0.0-beta.9 * @since 1.0.0-beta.14 Added `$request` parameter. * @since 1.0.0-beta.18 Fixed access plans link. * * @param LLMS_Membership $membership LLMS Membership. * @param WP_REST_Request $request Request object. * @return array Links for the given object. */ protected function prepare_links( $membership, $request ) { $links = parent::prepare_links( $membership, $request ); unset( $links['content'] ); $id = $membership->get( 'id' ); // Access plans. $links['access_plans'] = array( 'href' => add_query_arg( 'post_id', $id, rest_url( sprintf( '%s/%s', $this->namespace, 'access-plans' ) ) ), ); // Auto enrollment courses. $auto_enroll_courses = implode( ',', $membership->get_auto_enroll_courses() ); if ( $auto_enroll_courses ) { $links['auto_enrollment_courses'] = array( 'href' => add_query_arg( 'include', $auto_enroll_courses, rest_url( sprintf( '%s/%s', $this->namespace, 'courses' ) ) ), ); } // Enrollments. $links['enrollments'] = array( 'href' => rest_url( sprintf( '/%s/%s/%d/%s', $this->namespace, $this->rest_base, $id, 'enrollments' ) ), ); // Instructors. $links['instructors'] = array( 'href' => add_query_arg( 'post', $id, rest_url( sprintf( '%s/%s', $this->namespace, 'instructors' ) ) ), ); // Students. $links['students'] = array( 'href' => add_query_arg( 'enrolled_in', $id, rest_url( sprintf( '%s/%s', $this->namespace, 'students' ) ) ), ); /** * Filters the membership's links. * * @since 1.0.0-beta.9 * * @param array $links Links for the given membership. * @param LLMS_Membership $membership LLMS Membership object. */ $links = apply_filters( 'llms_rest_membership_links', $links, $membership ); return $links; } /** * Prepare a single object output for response. * * @since 1.0.0-beta.9 * * @param LLMS_Membership $membership Membership object. * @param WP_REST_Request $request Full details about the request. * @return array */ protected function prepare_object_for_response( $membership, $request ) { $data = parent::prepare_object_for_response( $membership, $request ); $context = $request->get_param( 'context' ); // Auto enroll. $data['auto_enroll'] = $membership->get_auto_enroll_courses(); // Catalog visibility. $data['catalog_visibility'] = $membership->get_product()->get_catalog_visibility(); // Categories. $data['categories'] = $membership->get_categories( array( 'fields' => 'ids', ) ); // Instructors. $instructors = $membership->get_instructors(); $instructors = empty( $instructors ) ? array() : wp_list_pluck( $instructors, 'id' ); $data['instructors'] = $instructors; // Restriction action. $data['restriction_action'] = $membership->get( 'restriction_redirect_type' ); $data['restriction_action'] = $data['restriction_action'] ? $data['restriction_action'] : 'none'; // Restriction message. $data['restriction_message'] = array( 'raw' => $membership->get( 'restriction_notice', $raw = true ), 'rendered' => do_shortcode( $membership->get( 'restriction_notice' ) ), ); // Restriction page id. if ( 'page' === $data['restriction_action'] || 'edit' === $context ) { $data['restriction_page_id'] = $membership->get( 'redirect_page_id' ); } // Restriction URL. if ( 'custom' === $data['restriction_action'] || 'edit' === $context ) { $data['restriction_url'] = $membership->get( 'redirect_custom_url' ); } // Tags. $data['tags'] = $membership->get_tags( array( 'fields' => 'ids', ) ); // Sales page type. $data['sales_page_type'] = $membership->get( 'sales_page_content_type' ); $data['sales_page_type'] = $data['sales_page_type'] ? $data['sales_page_type'] : 'none'; // Sales page id. if ( 'page' === $data['sales_page_type'] || 'edit' === $context ) { $data['sales_page_page_id'] = $membership->get( 'sales_page_content_page_id' ); } // Sales page url. if ( 'custom' === $data['sales_page_type'] || 'edit' === $context ) { $data['sales_page_url'] = $membership->get( 'sales_page_content_url' ); } /** * Filters the membership data for a response. * * @since 1.0.0-beta.9 * * @param array $data Array of lesson properties prepared for response. * @param LLMS_Membership $membership Membership object. * @param WP_REST_Request $request Full details about the request. */ $data = apply_filters( 'llms_rest_prepare_membership_object_response', $data, $membership, $request ); return $data; } /** * Register routes. * * @since 1.0.0-beta.9 * * @return void */ public function register_routes() { parent::register_routes(); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)/enrollments', array( 'args' => array( 'id' => array( 'description' => __( 'Unique Membership Identifier. The WordPress Post ID', 'lifterlms' ), 'type' => 'integer', ), ), array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this->enrollments_controller, 'get_items' ), 'permission_callback' => array( $this->enrollments_controller, 'get_items_permissions_check' ), 'args' => $this->enrollments_controller->get_collection_params(), ), 'schema' => array( $this->enrollments_controller, 'get_public_item_schema' ), ) ); } /** * Updates an existing single LLMS_Membership in the database. * * This method should be used for membership properties that require the membership id in order to be saved in the database. * * @since 1.0.0-beta.9 * @since 1.0.0-beta.25 Allow updating meta with the same value as the stored one. * * @param LLMS_Membership $membership LLMS_Membership instance. * @param WP_REST_Request $request Full details about the request. * @param array $schema The item schema. * @param array $prepared_item Array. * @param bool $creating Optional. Whether we're in creation or update phase. Default true (create). * @return bool|WP_Error True on success or false if nothing to update, WP_Error object if something went wrong during the update. */ protected function update_additional_object_fields( $membership, $request, $schema, $prepared_item, $creating = true ) { $error = new WP_Error(); // Auto enroll. if ( ! empty( $schema['properties']['auto_enroll'] ) && isset( $request['auto_enroll'] ) ) { $membership->add_auto_enroll_courses( $request['auto_enroll'], true ); } // Catalog visibility. if ( ! empty( $schema['properties']['catalog_visibility'] ) && isset( $request['catalog_visibility'] ) ) { $membership->get_product()->set_catalog_visibility( $request['catalog_visibility'] ); } // Instructors. if ( ! empty( $schema['properties']['instructors'] ) ) { $instructors = array(); if ( isset( $request['instructors'] ) ) { foreach ( $request['instructors'] as $instructor_id ) { $user_data = get_userdata( $instructor_id ); if ( ! empty( $user_data ) ) { $instructors[] = array( 'id' => $instructor_id, 'name' => $user_data->display_name, ); } } } // When creating, always make sure the instructors are set. // Note: `$membership->set_instructor( $instructors )` when `$instructors` is empty // will set the membership's author as membership's instructor. if ( $membership || ( ! $creating && isset( $request['instructors'] ) ) ) { $membership->set_instructors( $instructors ); } } $to_set = array(); /** * The following properties have a default value that contains a placeholder, e.g. `{{membership_id}}`, * that can be "expanded" only after the membership has been created. */ // Restriction message. if ( ! empty( $schema['properties']['restriction_message'] ) ) { if ( isset( $request['restriction_message'] ) ) { if ( is_string( $request['restriction_message'] ) ) { $to_set['restriction_notice'] = $request['restriction_message']; } elseif ( isset( $request['restriction_message']['raw'] ) ) { $to_set['restriction_notice'] = $request['restriction_message']['raw']; } } elseif ( $creating ) { $to_set['restriction_notice'] = $schema['properties']['restriction_message']['properties']['raw']['default']; } } // Needed until the following will be implemented: https://github.com/gocodebox/lifterlms/issues/908. // On creation, since the restriction message has a non empty default, the restriction_add_notice, // will be set to 'yes'. $to_set['restriction_add_notice'] = empty( $to_set['restriction_notice'] ) ? 'no' : 'yes'; // Are we creating a membership? TODO what about updating when message is empty? // If so, replace the placeholder with the actual membership id. if ( $creating ) { $_to_expand_props = array( 'restriction_notice',
Expand full source code Collapse full source code View on GitHub
Methods Methods
- __construct — Constructor.
- get_enrollments_collection_params — Retrieves the query params for the enrollments objects collection.
- get_filters_to_be_removed_for_response — Get action/filters to be removed before preparing the item for response.
- get_item_schema — Get the Membership's schema, conforming to JSON Schema.
- get_taxonomy_rest_base — Maps a taxonomy name to the relative rest base.
- prepare_item_for_database — Prepares a single post for create or update.
- prepare_links — Prepare links for the request.
- prepare_object_for_response — Prepare a single object output for response.
- register_routes — Register routes.
- update_additional_object_fields — Updates an existing single LLMS_Membership in the database.
Changelog Changelog
Version | Description |
---|---|
1.0.0-beta.9 | |
1.0.0-beta.14 | Introduced. |