Skip to content
Draft

Divi #3068

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3fd95a5
WIP: Initial commit of generated divi extension
brianhogg Dec 9, 2025
1b2d1a4
Removing plugin header from embedded extension file. Build of demo ex…
brianhogg Dec 9, 2025
c066256
WIP: Got front-end preview to work with shortcode output via computed…
brianhogg Dec 9, 2025
d5d9096
Using dummy hidden field to trigger a preview rendering.
brianhogg Dec 9, 2025
5f93ca1
WIP: Renaming files. I'm not getting an infinite loop in get_preview_…
brianhogg Dec 9, 2025
4477998
Fixing infinite loop by makin the slug of the Divi module different t…
brianhogg Dec 9, 2025
906863f
Changing to fragment instead of extra div.
brianhogg Dec 10, 2025
6713cb2
Adding custom icon to the module.
brianhogg Dec 11, 2025
9747689
WIP: Adding course selection dropdown. It doesn't seem to force anoth…
brianhogg Dec 11, 2025
6b2a52f
WIP: Attempt at adding Course Instructors with preview. It's generati…
brianhogg Dec 12, 2025
4da020a
WIP: Attempt at adding Course Syllabus with preview. It's lso generat…
brianhogg Dec 12, 2025
c96a8bb
Previews working with div instead of fragment. Handling for "current"…
brianhogg Dec 12, 2025
d823f0c
WIP: trying to add field for settings
brianhogg Dec 12, 2025
f34de91
WIP: Adding field with the right filter, but it's adding for every po…
brianhogg Dec 12, 2025
a3a8a23
Tried getting the toggle to persist after refreshing, but it does not…
brianhogg Dec 12, 2025
b3897d1
Pricing table module
brianhogg Dec 12, 2025
80065bc
Course progress module. Fixing typos.
brianhogg Dec 12, 2025
560260c
Course meta info module
brianhogg Dec 12, 2025
f2bec13
Changelog
brianhogg Dec 12, 2025
66cc469
Revert
brianhogg Dec 12, 2025
93543a1
Removing comments, setting version to plugin
brianhogg Dec 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelogs/divi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
significance: minor
type: added
entry: LifterLMS modules for Divi.
1 change: 1 addition & 0 deletions class-lifterlms.php
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@ public function init() {
include_once 'includes/class-llms-bricks.php';
include_once 'includes/class-llms-beaver-builder.php';
include_once 'includes/class-llms-beaver-builder-migrate.php';
include_once 'includes/divi/extension/my-extension.php';

do_action( 'lifterlms_init' );
}
Expand Down
1 change: 1 addition & 0 deletions includes/divi/extension/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SKIP_PREFLIGHT_CHECK=true
29 changes: 29 additions & 0 deletions includes/divi/extension/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.

# dependencies
/node_modules

# testing
/coverage

# production
#/scripts/bundle.min.js
#/scripts/builder-bundle.min.js
#/scripts/frontend-bundle.min.js
#/styles/bundle.min.css
#/styles/backend-style.min.css
#/styles/style-dbp.min.css
#/styles/style.min.css
#asset-manifest.json
#*.map

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
667 changes: 667 additions & 0 deletions includes/divi/extension/README.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions includes/divi/extension/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"builder.css": "/styles/backend-style.min.css",
"builder.js": "/scripts/builder-bundle.min.js",
"frontend.css": "/styles/backend-style.min.css",
"frontend.js": "/scripts/frontend-bundle.min.js"
}
105 changes: 105 additions & 0 deletions includes/divi/extension/includes/LifterLMS_Divi_Extension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

class LifterLMS_Divi_Extension extends DiviExtension {

/**
* The gettext domain for the extension's translations.
*
* @since 1.0.0
*
* @var string
*/
public $gettext_domain = 'lifterlms';

/**
* The extension's WP Plugin name.
*
* @var string
*/
public $name = 'lifterlms-divi';

/**
* The extension's version
*
* @var string
*/
public $version = LLMS_VERSION;

public function __construct( $name = 'lifterlms-divi', $args = array() ) {
$this->plugin_dir = plugin_dir_path( __FILE__ );
$this->plugin_dir_url = plugin_dir_url( $this->plugin_dir );

parent::__construct( $name, $args );

// Add field to Divi page settings modal.
add_filter( 'et_builder_page_settings_definitions', array( $this, 'add_page_settings_field' ) );

// Remove default LifterLMS content hooks if setting is enabled.
add_action( 'template_redirect', array( $this, 'maybe_remove_default_llms_content' ) );
}

/**
* Add field to Divi page settings modal
*
* @param array $fields Existing fields.
* @return array
*/
public function add_page_settings_field( $fields ) {

$fields['et_pb_llms_disable_default_content'] = array(
'type' => 'yes_no_button',
'id' => 'et_pb_llms_disable_default_content',
'label' => esc_html__( 'Disable Default LifterLMS Content', 'lifterlms' ),
'options' => array(
'off' => esc_html__( 'No', 'lifterlms' ),
'on' => esc_html__( 'Yes', 'lifterlms' ),
),
'default' => 'off',
'description' => esc_html__( 'Enable this to disable the default LifterLMS content output at the bottom of the page. Use this when you have manually added LifterLMS Divi modules or LifterLMS shortcodes.', 'lifterlms' ),
'tab_slug' => 'content',
'toggle_slug' => 'main_content',
);

return $fields;
}

/**
* Remove default LifterLMS content hooks if Divi setting is enabled
*
* @return void
*/
public function maybe_remove_default_llms_content() {
if ( ! is_singular( 'course' ) ) {
return;
}

global $post;
$disable_default = get_post_meta( $post->ID, '_et_pb_llms_disable_default_content', true );

if ( 'on' === $disable_default ) {
$this->remove_default_llms_hooks();
}
}

/**
* Remove default LifterLMS content hooks
*
* @return void
*/
private function remove_default_llms_hooks() {
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_single_meta_wrapper_start', 5 );
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_single_length', 10 );
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_single_difficulty', 20 );
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_single_course_tracks', 25 );
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_single_course_categories', 30 );
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_single_course_tags', 35 );
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_course_author', 40 );
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_single_meta_wrapper_end', 50 );
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_single_prerequisites', 55 );
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_pricing_table', 60 );
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_single_course_progress', 60 );
remove_action( 'lifterlms_single_course_after_summary', 'lifterlms_template_single_syllabus', 90 );
}
}

new LifterLMS_Divi_Extension();
35 changes: 35 additions & 0 deletions includes/divi/extension/includes/fields/Input/Input.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// External Dependencies
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can likely delete this

import React, { Component } from 'react';

// Internal Dependencies
import './style.css';

class Input extends Component {

static slug = 'lifterlms_input';

/**
* Handle input value change.
*
* @param {object} event
*/
_onChange = (event) => {
this.props._onChange(this.props.name, event.target.value);
}

render() {
return(
<input
id={`lifterlms-input-${this.props.name}`}
name={this.props.name}
value={this.props.value}
type='text'
className='lifterlms-input'
onChange={this._onChange}
placeholder='Your text here ...'
/>
);
}
}

export default Input;
42 changes: 42 additions & 0 deletions includes/divi/extension/includes/fields/Input/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
input.lifterlms-input {
background: #f1f5f9;
max-height: 30px;
border: 0;
border-radius: 3px;
padding: 7px 10px;
box-sizing: border-box;
transition: background 200ms ease;
color: #4C5866;
font-family: 'Open Sans', Helvetica, Roboto, Arial, sans-serif;
font-size: 13px;
font-weight: 600;
line-height: normal;
display: block;
width: 100%;
}

input.lifterlms-input:focus {
background: #e6ecf2;
}

input.lifterlms-input::-webkit-input-placeholder {
color: #98a7b8;
}

input.lifterlms-input:-moz-placeholder {
color: #98a7b8;
}

input.lifterlms-input::-moz-placeholder {
color: #98a7b8;
}

input.lifterlms-input:-ms-input-placeholder {
color: #98a7b8;
}

input.lifterlms-input[readonly] {
background: #ffffff !important;
border: 1px solid #eaedf0 !important;
cursor: not-allowed;
}
3 changes: 3 additions & 0 deletions includes/divi/extension/includes/fields/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Input from './Input/Input';

export default [Input];
11 changes: 11 additions & 0 deletions includes/divi/extension/includes/loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// External Dependencies
import $ from 'jquery';

// Internal Dependencies
import modules from './modules';
import fields from './fields';

$(window).on('et_builder_api_ready', (event, API) => {
API.registerModules(modules);
API.registerModalFields(fields);
});
14 changes: 14 additions & 0 deletions includes/divi/extension/includes/loader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

if ( ! class_exists( 'ET_Builder_Element' ) ) {
return;
}

$module_files = glob( __DIR__ . '/modules/*/*.php' );

// Load custom Divi Builder modules
foreach ( (array) $module_files as $module_file ) {
if ( $module_file && preg_match( "/\/modules\/\b([^\/]+)\/\\1\.php$/", $module_file ) ) {
require_once $module_file;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React, { Component, Fragment } from "react";
import "./style.css";

class CourseContinueButton extends Component {
static slug = "lifterlms_divi_course_continue_button";

render() {
const preview_html = this.props.__preview_html;
return (
<div dangerouslySetInnerHTML={{ __html: preview_html }} />
);
}
}

export default CourseContinueButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

class LLMS_Divi_Course_Continue_Button extends ET_Builder_Module {

public $slug = 'lifterlms_divi_course_continue_button';
public $vb_support = 'on';
public $icon_path;

protected $module_credits = array(
'module_uri' => 'https://lifterlms.com/',
'author' => 'LifterLMS',
'author_uri' => 'https://lifterlms.com',
);

public function init() {
$this->name = esc_html__( 'LifterLMS Course Continue Button', 'lifterlms' );
$this->icon_path = LLMS_PLUGIN_DIR . 'assets/images/lifterlms-icon-grey.svg';
}

public function get_fields() {
return array(
'dummy' => array(
'type' => 'hidden',
'default' => '1',
'option_category' => 'basic_option',
'computed_affects' => array( '__preview_html' ),
),
'course_id' => array(
'label' => esc_html__( 'Course', 'lifterlms' ),
'type' => 'select',
'option_category' => 'basic_option',
'options' => $this->get_course_options(),
'default' => 'current',
'computed_affects' => array( '__preview_html' ),
'description' => esc_html__( 'Select a course or leave blank to use the current page.', 'lifterlms' ),
),
'__preview_html' => array(
'type' => 'computed',
'computed_callback' => array( 'LLMS_Divi_Course_Continue_Button', 'get_preview_html' ),
'computed_depends_on' => array( 'course_id', 'dummy' ),
),
);
}

private function get_course_options() {
$options = array(
'current' => esc_html__( 'Select a course', 'lifterlms' ),
);

$courses = get_posts(
array(
'post_type' => 'course',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
'post_status' => 'publish',
)
);

foreach ( $courses as $course ) {
$options[ $course->ID ] = $course->post_title;
}

return $options;
}

static function get_preview_html( $args = array(), $conditional_tags = array(), $current_page = array() ) {
$course_id = ( ! empty( $args['course_id'] ) && is_numeric( $args['course_id'] ) ) ? absint( $args['course_id'] ) : absint( $current_page['id'] );
return do_shortcode( '[lifterlms_course_continue_button course_id="' . $course_id . '"]' );
}

public function render( $attrs, $content, $render_slug ) {
global $post;

$course_id = ! empty( $this->props['course_id'] ) ? $this->props['course_id'] : ( $post ? $post->ID : 0 );
return do_shortcode( '[lifterlms_course_continue_button course_id="' . absint( $course_id ) . '"]' );
}
}

new LLMS_Divi_Course_Continue_Button();
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* Module icon sizing in builder */
.lifterlms_divi_course_continue_button .et-fb-icon--svg,
.lifterlms_divi_course_continue_button .et-fb-icon--svg svg {
height: 16px;
width: 16px;
min-width: 16px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React, { Component, Fragment } from "react";
import "./style.css";

class CourseInstructors extends Component {
static slug = "lifterlms_divi_course_instructors";

render() {
const preview_html = this.props.__preview_html;
return (
<div dangerouslySetInnerHTML={{ __html: preview_html }} />
);
}
}

export default CourseInstructors;
Loading
Loading