gocodebox / lifterlms

LifterLMS, a WordPress LMS Solution: Easily create, sell, and protect engaging online courses.
https://lifterlms.com
GNU General Public License v3.0
184 stars 135 forks source link

Refactor Merge Codes API #560

Open actual-saurabh opened 6 years ago

actual-saurabh commented 6 years ago

Right now, to completely add a merge code, you need to add a filter at two places:

First, you filter the button dropdown: https://github.com/gocodebox/lifterlms/blob/master/includes/admin/llms.functions.admin.php#L143

Then you filter the actual search-replace key-value pairs here:

https://github.com/gocodebox/lifterlms/blob/master/includes/certificates/class.llms.certificate.user.php#L134

So, the primary objective is to have one reference for merge codes that can be filtered in one go.

Additionally, we could have a merge code API similar to the erstwhile Metabox API of WordPress where you could possibly add a merge code:

llms_add_mergecode( $code, $type, $replacement_function );
llms_remove_mergecode( $code, $type );
llms_update_mergecode( $code, $type, $replacement_function );

where

and create additional wrappers that just call core functions

llms_add_certificate_mergecode( $code, $replacement_function );
llms_remove_certificate_mergecode( $code );
llms_update_certificate_mergecode( $code, $replacement_function );

llms_add_email_mergecode( $code, $replacement_function );
llms_remove_email_mergecode( $code );
llms_update_email_mergecode( $code, $replacement_function );

The callbacks would receive all the parameters available in the current filters. Empty replacement callbacks will be understood by the API to be handled internally (as it is now) and can be replaced with custom code far more easily, I feel.

actual-saurabh commented 6 years ago

In addition, like the ShortCode API this could have :

llms_do_mergecode( $content );

This could be really useful to generate parsed content conveniently, for example, to generate dynamic previews using AJAX calls.

llms_has_mergecode( $content, $code );

This could be really useful to do specific stuff like include some CSS (for example to add a suggested course catalog in the email, and such).

actual-saurabh commented 6 years ago

Covers #358.

actual-saurabh commented 6 years ago

More notes:

Engagements can be described in terms of three objects/entities:

  1. Student
  2. Trigger Event (completed, enrolled, purchased, passed or failed: the actual event that triggered the engagement)
  3. Trigger Object (a membership, a course, a lesson or a quiz)
  4. Trigger Result (to earn a certificate, receive an email or get an achievement)

Each of these objects have properties (post attributes or meta).

A more expansive merge code api should be able to pick any of these properties using _ as a word boundary

{object_entity_name}_{property_name}

Student Codes

student_{user_data}

where user_data is any of the properties available in get_userdata()

student_{meta_key}

Where meta_key is without the llms_ prefix (so, instead of llms_certificate it is certificate) for LifterLMS's post types and the full meta key (including prefix, if any) for custom or third party meta.

Trigger Event Codes

In a particular engagement, the only information about the trigger that is relevant is the timestamp of the trigger. Almost everything else is either information about the triggered engagement (say certificate) or the object of the trigger (course).

{trigger_event}_date

Engagement & Trigger Object Codes

Since both the object of an engagement and the engagement itself are posts, merge codes could work out of the box like this:

{post_type}_{post_attribute} {post_type}_{meta_key}

Where post_type is without the llms_ prefix (so, instead of llms_certificate it is certificate) for LifterLMS's post types and the full post type name (including prefix, if any) for others.

post_attribute is the name of any column in the {wp}_posts table without the post_ prefix.

Similarly, meta_key is without the llms_ prefix for internal meta keys and full key name for custom meta data.

So,

could all work out of the box.

The default WP mechanism of distinguishing descriptive meta from administrative meta using a _ prefix should work to decide what meta data will be automatically available as a merge code.

Finally, if we create schema files for LLMS objects, where each meta key and attribute could be given a text description and that could be used for displaying/describing merge codes in user understandable terms.

This way, no one would have to separately register specific codes in most cases, although explicit registration and de-registration would still be allowed for use cases that fall outside this mechanism.

actual-saurabh commented 5 years ago

Global Codes

Some merge codes are related to the WP site or the LMS and could work irrespective of where they are used. They can be namespaced as

site_{key_name}

From https://developer.wordpress.org/reference/functions/get_bloginfo/, the following can be picked up:

Some branding related stuff can also be added:

LifterLMS specific stuff should also be added to the site namespace:

(and many more that I can't think of right away)

Although these can be added manually, a merge code would help when content is transferred from one site to another.

actual-saurabh commented 5 years ago

Course Codes on Course Elements

In addition to cases where a course or membership is the object of the trigger, for course elements, it might make sense to also make the course level merge codes available.

In the current trigger object is in a course, fetch the course and allow using its merge codes as well.

actual-saurabh commented 5 years ago

Handling unavailable merge codes

If the same engagement result is used for multiple engagement objects (same certificate for a course and a section of another course), some merge codes might not be available in some of the cases.

In such a case, instead of displaying the raw merge code, the better idea seems to be to remove the merge code altogether, log the error and display a notice to admin.