added additional plugins
This commit is contained in:
parent
c85895d306
commit
00e60ec1b7
132 changed files with 27514 additions and 0 deletions
1
native/wordpress/learndash-start-button/.gitignore
vendored
Normal file
1
native/wordpress/learndash-start-button/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
135
native/wordpress/learndash-start-button/LICENSE
Normal file
135
native/wordpress/learndash-start-button/LICENSE
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software,
|
||||
and (2) offer you this license which gives you legal permission to
|
||||
copy, distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on,
|
||||
we want its recipients to know that what they have is not the
|
||||
original, so that any problems introduced by others will not reflect
|
||||
on the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at
|
||||
all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
[... full license continues unchanged until end ...]
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these
|
||||
terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
7
native/wordpress/learndash-start-button/README.md
Normal file
7
native/wordpress/learndash-start-button/README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# learndash-start-button
|
||||
|
||||
This is a plugin to add simple Start buttons to improve the learndash experience for the end user. This adds shortcodes and Gutenberg blocks to make placement easy. This is intended for Wordpress Gutenberg/FSE sites.
|
||||
|
||||
Intended usage: Add a "Start First Course" to group pages, and add a "Start Course Now" to course pages.
|
||||
|
||||
Why I made this: because users opened their learndash pages and were lost. I literally had users sitting staring at a screen unsure as to how to proceed. I have requested this functionality from Learndash time and again, so I decided to make it myself.
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* LearnDash Start Course/Group Buttons - Block Editor Styles
|
||||
*/
|
||||
|
||||
/* Block wrapper in editor */
|
||||
.wp-block-ldsb-start-button {
|
||||
padding: 10px;
|
||||
border: 1px dashed #ddd;
|
||||
background: #f9f9f9;
|
||||
border-radius: 4px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
/* Prevent button interaction in editor */
|
||||
.wp-block-ldsb-start-button .ldsb-start-button {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Selected block styling */
|
||||
.wp-block-ldsb-start-button.is-selected {
|
||||
border-color: #007cba;
|
||||
background: #f0f8ff;
|
||||
}
|
||||
|
||||
/* Button preview in editor - import main styles */
|
||||
.wp-block-ldsb-start-button .ldsb-button-wrapper {
|
||||
margin: 10px 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.wp-block-ldsb-start-button .ldsb-start-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 16px 32px;
|
||||
background-color: #2d7a2d;
|
||||
color: #f6f6f6;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.5px;
|
||||
box-shadow: 0 4px 12px rgba(45, 122, 45, 0.3);
|
||||
border: none;
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu,
|
||||
Cantarell, sans-serif;
|
||||
}
|
||||
|
||||
.wp-block-ldsb-start-button .ldsb-button-text {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.wp-block-ldsb-start-button .ldsb-button-arrow {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Block placeholder when no course selected */
|
||||
.wp-block-ldsb-start-button.no-course::before {
|
||||
content: "LearnDash Start Course Button: Configure course ID in block settings";
|
||||
display: block;
|
||||
color: #757575;
|
||||
font-size: 13px;
|
||||
margin-bottom: 10px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Alignment in editor preview */
|
||||
.wp-block-ldsb-start-button.align-left .ldsb-button-wrapper {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.wp-block-ldsb-start-button.align-center .ldsb-button-wrapper {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.wp-block-ldsb-start-button.align-right .ldsb-button-wrapper {
|
||||
text-align: right;
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
// Silence is golden.
|
||||
173
native/wordpress/learndash-start-button/assets/css/style.css
Normal file
173
native/wordpress/learndash-start-button/assets/css/style.css
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/**
|
||||
* LearnDash Start Course/Group Buttons - Frontend Styles
|
||||
*
|
||||
* WCAG AAA Compliant Colors:
|
||||
* Background: #2D7A2D (Brightest green that passes AAA with #f6f6f6)
|
||||
* Text: #f6f6f6
|
||||
* Contrast Ratio: 7:1
|
||||
*/
|
||||
|
||||
.ldsb-button-wrapper {
|
||||
margin: 20px 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ldsb-start-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 16px 32px;
|
||||
background-color: #2d7a2d; /* Brightest green that passes WCAG AAA with #f6f6f6 */
|
||||
color: #f6f6f6;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.5px;
|
||||
box-shadow: 0 4px 12px rgba(45, 122, 45, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu,
|
||||
Cantarell, sans-serif;
|
||||
}
|
||||
|
||||
.ldsb-start-button:hover {
|
||||
background-color: #245f24;
|
||||
color: #ffffff;
|
||||
box-shadow: 0 6px 20px rgba(45, 122, 45, 0.4);
|
||||
transform: translateY(-2px);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.ldsb-start-button:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 2px 8px rgba(45, 122, 45, 0.3);
|
||||
}
|
||||
|
||||
.ldsb-start-button:focus {
|
||||
outline: 3px solid #5ea85e;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.ldsb-button-text {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.ldsb-button-arrow {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
transition: transform 0.3s ease;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ldsb-start-button:hover .ldsb-button-arrow {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
/* Ensure proper visibility in different contexts */
|
||||
.entry-content .ldsb-start-button,
|
||||
.learndash-wrapper .ldsb-start-button {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
/* Alignment options - using both text-align and flex for better compatibility */
|
||||
.ldsb-button-wrapper.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ldsb-button-wrapper.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ldsb-button-wrapper.align-center .ldsb-start-button {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.ldsb-button-wrapper.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ldsb-button-wrapper.align-right .ldsb-start-button {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* Full width option */
|
||||
.ldsb-button-wrapper.align-full .ldsb-start-button,
|
||||
.ldsb-button-wrapper.full-width .ldsb-start-button {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Wide alignment */
|
||||
.ldsb-button-wrapper.align-wide {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ldsb-button-wrapper.align-wide .ldsb-start-button {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Mobile responsive styles */
|
||||
@media (max-width: 480px) {
|
||||
.ldsb-start-button {
|
||||
padding: 14px 24px;
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ldsb-button-text {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.ldsb-button-arrow {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablet styles */
|
||||
@media (min-width: 481px) and (max-width: 768px) {
|
||||
.ldsb-start-button {
|
||||
padding: 15px 28px;
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.ldsb-button-text {
|
||||
font-size: 17px;
|
||||
}
|
||||
}
|
||||
|
||||
/* High contrast mode support */
|
||||
@media (prefers-contrast: high) {
|
||||
.ldsb-start-button {
|
||||
border: 2px solid currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduced motion support */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.ldsb-start-button,
|
||||
.ldsb-button-arrow {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.ldsb-start-button:hover {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.ldsb-start-button:hover .ldsb-button-arrow {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
2
native/wordpress/learndash-start-button/assets/index.php
Normal file
2
native/wordpress/learndash-start-button/assets/index.php
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
// Silence is golden.
|
||||
566
native/wordpress/learndash-start-button/assets/js/block.js
Normal file
566
native/wordpress/learndash-start-button/assets/js/block.js
Normal file
|
|
@ -0,0 +1,566 @@
|
|||
/**
|
||||
* LearnDash Start Course Button - Gutenberg Blocks
|
||||
*
|
||||
* Registers custom Gutenberg blocks for Start Course and Start Group buttons
|
||||
*/
|
||||
|
||||
(function (wp) {
|
||||
"use strict";
|
||||
|
||||
// Destructure required WordPress packages
|
||||
const { __ } = wp.i18n;
|
||||
const { createElement: el } = wp.element;
|
||||
const { registerBlockType } = wp.blocks;
|
||||
const {
|
||||
TextControl,
|
||||
ToggleControl,
|
||||
PanelBody,
|
||||
PanelRow,
|
||||
SelectControl,
|
||||
Notice,
|
||||
} = wp.components;
|
||||
const { InspectorControls, BlockControls, AlignmentToolbar, useBlockProps } =
|
||||
wp.blockEditor;
|
||||
const { Fragment } = wp.element;
|
||||
|
||||
// SVG Arrow Icon
|
||||
const arrowIcon = el(
|
||||
"svg",
|
||||
{
|
||||
className: "ldsb-button-arrow",
|
||||
width: "24",
|
||||
height: "24",
|
||||
viewBox: "0 0 24 24",
|
||||
fill: "none",
|
||||
xmlns: "http://www.w3.org/2000/svg",
|
||||
},
|
||||
el("path", {
|
||||
d: "M5 12H19M19 12L12 5M19 12L12 19",
|
||||
stroke: "currentColor",
|
||||
strokeWidth: "2",
|
||||
strokeLinecap: "round",
|
||||
strokeLinejoin: "round",
|
||||
}),
|
||||
);
|
||||
|
||||
// Course block icon
|
||||
const courseBlockIcon = el(
|
||||
"svg",
|
||||
{
|
||||
width: "24",
|
||||
height: "24",
|
||||
viewBox: "0 0 24 24",
|
||||
fill: "none",
|
||||
},
|
||||
el("path", {
|
||||
d: "M13 7L18 12M18 12L13 17M18 12H6",
|
||||
stroke: "currentColor",
|
||||
strokeWidth: "2",
|
||||
strokeLinecap: "round",
|
||||
strokeLinejoin: "round",
|
||||
}),
|
||||
el("rect", {
|
||||
x: "3",
|
||||
y: "3",
|
||||
width: "18",
|
||||
height: "18",
|
||||
rx: "2",
|
||||
stroke: "currentColor",
|
||||
strokeWidth: "2",
|
||||
}),
|
||||
);
|
||||
|
||||
// Group block icon
|
||||
const groupBlockIcon = el(
|
||||
"svg",
|
||||
{
|
||||
width: "24",
|
||||
height: "24",
|
||||
viewBox: "0 0 24 24",
|
||||
fill: "none",
|
||||
},
|
||||
el("path", {
|
||||
d: "M17 21V19C17 17.9391 16.5786 16.9217 15.8284 16.1716C15.0783 15.4214 14.0609 15 13 15H5C3.93913 15 2.92172 15.4214 2.17157 16.1716C1.42143 16.9217 1 17.9391 1 19V21",
|
||||
stroke: "currentColor",
|
||||
strokeWidth: "2",
|
||||
strokeLinecap: "round",
|
||||
strokeLinejoin: "round",
|
||||
}),
|
||||
el("circle", {
|
||||
cx: "9",
|
||||
cy: "7",
|
||||
r: "4",
|
||||
stroke: "currentColor",
|
||||
strokeWidth: "2",
|
||||
}),
|
||||
el("path", {
|
||||
d: "M23 21V19C22.9993 18.1137 22.7044 17.2528 22.1614 16.5523C21.6184 15.8519 20.8581 15.3516 20 15.13",
|
||||
stroke: "currentColor",
|
||||
strokeWidth: "2",
|
||||
strokeLinecap: "round",
|
||||
strokeLinejoin: "round",
|
||||
}),
|
||||
el("path", {
|
||||
d: "M16 3.13C16.8604 3.35031 17.623 3.85071 18.1676 4.55232C18.7122 5.25392 19.0078 6.11683 19.0078 7.005C19.0078 7.89318 18.7122 8.75608 18.1676 9.45769C17.623 10.1593 16.8604 10.6597 16 10.88",
|
||||
stroke: "currentColor",
|
||||
strokeWidth: "2",
|
||||
strokeLinecap: "round",
|
||||
strokeLinejoin: "round",
|
||||
}),
|
||||
);
|
||||
|
||||
// Register the Course Start button block
|
||||
registerBlockType("ldsb/start-button", {
|
||||
title: __("LearnDash Start Course Button", "learndash-start-button"),
|
||||
description: __(
|
||||
"A prominent button to start LearnDash courses",
|
||||
"learndash-start-button",
|
||||
),
|
||||
icon: courseBlockIcon,
|
||||
category: "common",
|
||||
keywords: [
|
||||
__("learndash", "learndash-start-button"),
|
||||
__("start", "learndash-start-button"),
|
||||
__("course", "learndash-start-button"),
|
||||
__("button", "learndash-start-button"),
|
||||
],
|
||||
attributes: {
|
||||
courseId: {
|
||||
type: "number",
|
||||
default: 0,
|
||||
},
|
||||
buttonText: {
|
||||
type: "string",
|
||||
default: "Start Course",
|
||||
},
|
||||
newTab: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
},
|
||||
alignment: {
|
||||
type: "string",
|
||||
default: "left",
|
||||
enum: ["left", "center", "right"],
|
||||
},
|
||||
},
|
||||
supports: {
|
||||
align: false, // We handle alignment internally
|
||||
className: true,
|
||||
html: false,
|
||||
},
|
||||
|
||||
// Edit function - what you see in the editor
|
||||
edit: function (props) {
|
||||
const {
|
||||
attributes: { courseId, buttonText, newTab, alignment },
|
||||
setAttributes,
|
||||
className,
|
||||
} = props;
|
||||
|
||||
const blockProps = useBlockProps({
|
||||
className: `align-${alignment} ${courseId === 0 ? "no-course" : ""}`,
|
||||
});
|
||||
|
||||
// Update alignment
|
||||
function onChangeAlignment(newAlignment) {
|
||||
setAttributes({ alignment: newAlignment || "left" });
|
||||
}
|
||||
|
||||
return el(
|
||||
Fragment,
|
||||
{},
|
||||
// Block Controls (toolbar)
|
||||
el(
|
||||
BlockControls,
|
||||
{},
|
||||
el(AlignmentToolbar, {
|
||||
value: alignment,
|
||||
onChange: onChangeAlignment,
|
||||
alignmentControls: [
|
||||
{
|
||||
icon: "editor-alignleft",
|
||||
title: __("Align left", "learndash-start-button"),
|
||||
align: "left",
|
||||
},
|
||||
{
|
||||
icon: "editor-aligncenter",
|
||||
title: __("Align center", "learndash-start-button"),
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
icon: "editor-alignright",
|
||||
title: __("Align right", "learndash-start-button"),
|
||||
align: "right",
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
|
||||
// Inspector Controls (sidebar)
|
||||
el(
|
||||
InspectorControls,
|
||||
{},
|
||||
el(
|
||||
PanelBody,
|
||||
{
|
||||
title: __("Button Settings", "learndash-start-button"),
|
||||
initialOpen: true,
|
||||
},
|
||||
el(
|
||||
PanelRow,
|
||||
{},
|
||||
el(TextControl, {
|
||||
label: __("Course ID", "learndash-start-button"),
|
||||
help: __(
|
||||
"Enter the LearnDash course ID. Leave empty to use current course.",
|
||||
"learndash-start-button",
|
||||
),
|
||||
value: courseId || "",
|
||||
onChange: function (value) {
|
||||
var parsed = parseInt(value, 10);
|
||||
setAttributes({ courseId: isNaN(parsed) || parsed < 0 ? 0 : parsed });
|
||||
},
|
||||
type: "number",
|
||||
min: 0,
|
||||
}),
|
||||
),
|
||||
el(
|
||||
PanelRow,
|
||||
{},
|
||||
el(TextControl, {
|
||||
label: __("Button Text", "learndash-start-button"),
|
||||
help: __(
|
||||
"The text to display on the button",
|
||||
"learndash-start-button",
|
||||
),
|
||||
value: buttonText,
|
||||
onChange: function (value) {
|
||||
setAttributes({ buttonText: value || "Start Course" });
|
||||
},
|
||||
}),
|
||||
),
|
||||
el(
|
||||
PanelRow,
|
||||
{},
|
||||
el(ToggleControl, {
|
||||
label: __("Open in New Tab", "learndash-start-button"),
|
||||
help: __(
|
||||
"Open the course in a new browser tab",
|
||||
"learndash-start-button",
|
||||
),
|
||||
checked: newTab,
|
||||
onChange: function (value) {
|
||||
setAttributes({ newTab: value });
|
||||
},
|
||||
}),
|
||||
),
|
||||
),
|
||||
|
||||
// Usage instructions panel
|
||||
el(
|
||||
PanelBody,
|
||||
{
|
||||
title: __("Usage Instructions", "learndash-start-button"),
|
||||
initialOpen: false,
|
||||
},
|
||||
el(
|
||||
"div",
|
||||
{ className: "ldsb-help-text" },
|
||||
el(
|
||||
"p",
|
||||
{},
|
||||
__("This button will automatically:", "learndash-start-button"),
|
||||
),
|
||||
el(
|
||||
"ul",
|
||||
{},
|
||||
el(
|
||||
"li",
|
||||
{},
|
||||
__(
|
||||
"• Link to the first lesson if available",
|
||||
"learndash-start-button",
|
||||
),
|
||||
),
|
||||
el(
|
||||
"li",
|
||||
{},
|
||||
__(
|
||||
'• Show "Login to Start" for logged-out users',
|
||||
"learndash-start-button",
|
||||
),
|
||||
),
|
||||
el(
|
||||
"li",
|
||||
{},
|
||||
__(
|
||||
'• Show "Enroll to Start" for non-enrolled users',
|
||||
"learndash-start-button",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Block Preview
|
||||
el(
|
||||
"div",
|
||||
blockProps,
|
||||
el(
|
||||
"div",
|
||||
{
|
||||
className: `ldsb-button-wrapper align-${alignment}`,
|
||||
style: { textAlign: alignment },
|
||||
},
|
||||
el(
|
||||
"a",
|
||||
{
|
||||
className: "ldsb-start-button",
|
||||
href: "#",
|
||||
onClick: function (e) {
|
||||
e.preventDefault();
|
||||
},
|
||||
},
|
||||
el("span", { className: "ldsb-button-text" }, buttonText),
|
||||
arrowIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
// Save function - null because this is a dynamic block
|
||||
save: function () {
|
||||
return null; // Dynamic block rendered by PHP
|
||||
},
|
||||
});
|
||||
|
||||
// Register the Group Start button block
|
||||
registerBlockType("ldsb/start-group", {
|
||||
title: __("LearnDash Start Group Work", "learndash-start-button"),
|
||||
description: __(
|
||||
"A button to start the first course in a LearnDash group",
|
||||
"learndash-start-button",
|
||||
),
|
||||
icon: groupBlockIcon,
|
||||
category: "common",
|
||||
keywords: [
|
||||
__("learndash", "learndash-start-button"),
|
||||
__("group", "learndash-start-button"),
|
||||
__("start", "learndash-start-button"),
|
||||
__("button", "learndash-start-button"),
|
||||
],
|
||||
attributes: {
|
||||
groupId: {
|
||||
type: "number",
|
||||
default: 0,
|
||||
},
|
||||
buttonText: {
|
||||
type: "string",
|
||||
default: "Start First Course",
|
||||
},
|
||||
newTab: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
},
|
||||
alignment: {
|
||||
type: "string",
|
||||
default: "left",
|
||||
enum: ["left", "center", "right"],
|
||||
},
|
||||
},
|
||||
supports: {
|
||||
align: false,
|
||||
className: true,
|
||||
html: false,
|
||||
},
|
||||
|
||||
// Edit function
|
||||
edit: function (props) {
|
||||
const {
|
||||
attributes: { groupId, buttonText, newTab, alignment },
|
||||
setAttributes,
|
||||
className,
|
||||
} = props;
|
||||
|
||||
const blockProps = useBlockProps({
|
||||
className: `align-${alignment} ${groupId === 0 ? "no-group" : ""}`,
|
||||
});
|
||||
|
||||
function onChangeAlignment(newAlignment) {
|
||||
setAttributes({ alignment: newAlignment || "left" });
|
||||
}
|
||||
|
||||
return el(
|
||||
Fragment,
|
||||
{},
|
||||
// Block Controls
|
||||
el(
|
||||
BlockControls,
|
||||
{},
|
||||
el(AlignmentToolbar, {
|
||||
value: alignment,
|
||||
onChange: onChangeAlignment,
|
||||
alignmentControls: [
|
||||
{
|
||||
icon: "editor-alignleft",
|
||||
title: __("Align left", "learndash-start-button"),
|
||||
align: "left",
|
||||
},
|
||||
{
|
||||
icon: "editor-aligncenter",
|
||||
title: __("Align center", "learndash-start-button"),
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
icon: "editor-alignright",
|
||||
title: __("Align right", "learndash-start-button"),
|
||||
align: "right",
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
|
||||
// Inspector Controls
|
||||
el(
|
||||
InspectorControls,
|
||||
{},
|
||||
el(
|
||||
PanelBody,
|
||||
{
|
||||
title: __("Group Button Settings", "learndash-start-button"),
|
||||
initialOpen: true,
|
||||
},
|
||||
el(
|
||||
PanelRow,
|
||||
{},
|
||||
el(TextControl, {
|
||||
label: __("Group ID", "learndash-start-button"),
|
||||
help: __(
|
||||
"Enter the LearnDash group ID. Leave empty to use current group.",
|
||||
"learndash-start-button",
|
||||
),
|
||||
value: groupId || "",
|
||||
onChange: function (value) {
|
||||
var parsed = parseInt(value, 10);
|
||||
setAttributes({ groupId: isNaN(parsed) || parsed < 0 ? 0 : parsed });
|
||||
},
|
||||
type: "number",
|
||||
min: 0,
|
||||
}),
|
||||
),
|
||||
el(
|
||||
PanelRow,
|
||||
{},
|
||||
el(TextControl, {
|
||||
label: __("Button Text", "learndash-start-button"),
|
||||
help: __(
|
||||
"The text to display on the button",
|
||||
"learndash-start-button",
|
||||
),
|
||||
value: buttonText,
|
||||
onChange: function (value) {
|
||||
setAttributes({ buttonText: value || "Start First Course" });
|
||||
},
|
||||
}),
|
||||
),
|
||||
el(
|
||||
PanelRow,
|
||||
{},
|
||||
el(ToggleControl, {
|
||||
label: __("Open in New Tab", "learndash-start-button"),
|
||||
help: __(
|
||||
"Open the course in a new browser tab",
|
||||
"learndash-start-button",
|
||||
),
|
||||
checked: newTab,
|
||||
onChange: function (value) {
|
||||
setAttributes({ newTab: value });
|
||||
},
|
||||
}),
|
||||
),
|
||||
),
|
||||
|
||||
el(
|
||||
PanelBody,
|
||||
{
|
||||
title: __("How It Works", "learndash-start-button"),
|
||||
initialOpen: false,
|
||||
},
|
||||
el(
|
||||
"div",
|
||||
{ className: "ldsb-help-text" },
|
||||
el("p", {}, __("This button will:", "learndash-start-button")),
|
||||
el(
|
||||
"ul",
|
||||
{},
|
||||
el(
|
||||
"li",
|
||||
{},
|
||||
__(
|
||||
"• Link to the first course in the group",
|
||||
"learndash-start-button",
|
||||
),
|
||||
),
|
||||
el(
|
||||
"li",
|
||||
{},
|
||||
__(
|
||||
"• Go to the first lesson if available",
|
||||
"learndash-start-button",
|
||||
),
|
||||
),
|
||||
el(
|
||||
"li",
|
||||
{},
|
||||
__(
|
||||
'• Show "Login to Start" for logged-out users',
|
||||
"learndash-start-button",
|
||||
),
|
||||
),
|
||||
el(
|
||||
"li",
|
||||
{},
|
||||
__(
|
||||
'• Show "Join Group to Start" for non-members',
|
||||
"learndash-start-button",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Block Preview
|
||||
el(
|
||||
"div",
|
||||
blockProps,
|
||||
el(
|
||||
"div",
|
||||
{
|
||||
className: `ldsb-button-wrapper align-${alignment}`,
|
||||
style: { textAlign: alignment },
|
||||
},
|
||||
el(
|
||||
"a",
|
||||
{
|
||||
className: "ldsb-start-button ldsb-group-button",
|
||||
href: "#",
|
||||
onClick: function (e) {
|
||||
e.preventDefault();
|
||||
},
|
||||
},
|
||||
el("span", { className: "ldsb-button-text" }, buttonText),
|
||||
arrowIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
save: function () {
|
||||
return null; // Dynamic block
|
||||
},
|
||||
});
|
||||
})(window.wp);
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
// Silence is golden.
|
||||
2
native/wordpress/learndash-start-button/index.php
Normal file
2
native/wordpress/learndash-start-button/index.php
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
// Silence is golden.
|
||||
|
|
@ -0,0 +1,677 @@
|
|||
<?php
|
||||
/**
|
||||
* Plugin Name: LearnDash Start Course Button
|
||||
* Plugin URI: https://sspmedia.ca/wordpress/
|
||||
* Description: Adds prominent "Start Course" and "Start Group Work" buttons for LearnDash with shortcode and Gutenberg block support
|
||||
* Version: 1.0.0
|
||||
* Author: SSP Media
|
||||
* License: GPL v2 or later
|
||||
* Text Domain: learndash-start-button
|
||||
* Domain Path: /languages
|
||||
* Requires at least: 5.0
|
||||
* Requires PHP: 7.2
|
||||
* WC requires at least: 7.0
|
||||
* WC tested up to: 9.0
|
||||
*
|
||||
* @package LearnDashStartCourseButton
|
||||
*/
|
||||
|
||||
// Prevent direct access - Wordfence compatible
|
||||
if (!defined('ABSPATH')) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
// Define plugin constants
|
||||
if (!defined('LDSB_VERSION')) {
|
||||
define('LDSB_VERSION', '1.0.0');
|
||||
}
|
||||
if (!defined('LDSB_PLUGIN_URL')) {
|
||||
define('LDSB_PLUGIN_URL', plugin_dir_url(__FILE__));
|
||||
}
|
||||
if (!defined('LDSB_PLUGIN_PATH')) {
|
||||
define('LDSB_PLUGIN_PATH', plugin_dir_path(__FILE__));
|
||||
}
|
||||
if (!defined('LDSB_PLUGIN_BASENAME')) {
|
||||
define('LDSB_PLUGIN_BASENAME', plugin_basename(__FILE__));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check plugin dependencies
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return bool True if dependencies are met, false otherwise
|
||||
*/
|
||||
function ldsb_check_dependencies() {
|
||||
$deps_met = true;
|
||||
$notices = array();
|
||||
|
||||
// Check for LearnDash
|
||||
if (!defined('LEARNDASH_VERSION')) {
|
||||
$deps_met = false;
|
||||
$notices[] = __('LearnDash Start Course Button requires LearnDash LMS to be installed and activated.', 'learndash-start-button');
|
||||
} elseif (version_compare(LEARNDASH_VERSION, '3.0', '<')) {
|
||||
$deps_met = false;
|
||||
$notices[] = __('LearnDash Start Course Button requires LearnDash version 3.0 or higher.', 'learndash-start-button');
|
||||
}
|
||||
|
||||
// Display admin notices if dependencies not met
|
||||
if (!$deps_met && is_admin() && !empty($notices)) {
|
||||
add_action('admin_notices', function() use ($notices) {
|
||||
foreach ($notices as $notice) {
|
||||
echo '<div class="notice notice-error"><p>' . esc_html($notice) . '</p></div>';
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
add_action('plugins_loaded', 'ldsb_check_dependencies');
|
||||
|
||||
/**
|
||||
* Declare WooCommerce HPOS compatibility
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
add_action('before_woocommerce_init', function() {
|
||||
if (class_exists('\Automattic\WooCommerce\Utilities\FeaturesUtil')) {
|
||||
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('custom_order_tables', __FILE__, true);
|
||||
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('cart_checkout_blocks', __FILE__, true);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Enqueue plugin styles - Only on LearnDash pages
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
function ldsb_enqueue_styles() {
|
||||
// Only load on singular pages or LearnDash archives
|
||||
if (!is_singular() && !is_post_type_archive('sfwd-courses') && !is_post_type_archive('groups') && !is_tax('ld_course_category') && !is_tax('ld_course_tag') && !is_tax('ld_group_category') && !is_tax('ld_group_tag')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if current post is LearnDash content or has our shortcode
|
||||
if (is_singular()) {
|
||||
global $post;
|
||||
|
||||
// Validate post object exists
|
||||
if (!$post || !is_object($post) || !isset($post->post_content)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check post type
|
||||
$ld_post_types = array('sfwd-courses', 'sfwd-lessons', 'sfwd-topic', 'sfwd-quiz', 'groups');
|
||||
$is_ld_content = in_array(get_post_type(), $ld_post_types);
|
||||
|
||||
// Check for shortcodes
|
||||
$has_course_shortcode = has_shortcode($post->post_content, 'learndash_start_button');
|
||||
$has_group_shortcode = has_shortcode($post->post_content, 'learndash_start_group');
|
||||
|
||||
// Check for blocks
|
||||
$has_course_block = has_block('ldsb/start-button', $post);
|
||||
$has_group_block = has_block('ldsb/start-group', $post);
|
||||
|
||||
if (!$is_ld_content && !$has_course_shortcode && !$has_group_shortcode && !$has_course_block && !$has_group_block) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wp_enqueue_style(
|
||||
'ldsb-button-styles',
|
||||
LDSB_PLUGIN_URL . 'assets/css/style.css',
|
||||
array(),
|
||||
LDSB_VERSION,
|
||||
'all'
|
||||
);
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'ldsb_enqueue_styles');
|
||||
|
||||
/**
|
||||
* Get first lesson URL with compatibility checks
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param int $course_id The course ID
|
||||
* @return string|false The first lesson URL or course URL, false on failure
|
||||
*/
|
||||
function ldsb_get_first_lesson_url($course_id) {
|
||||
$course_url = get_permalink($course_id);
|
||||
|
||||
// If we can't get the course URL, return false
|
||||
if (!$course_url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try new LearnDash 4.0+ method first
|
||||
if (function_exists('learndash_course_get_children_of_step')) {
|
||||
$lessons = learndash_course_get_children_of_step($course_id, $course_id, 'sfwd-lessons');
|
||||
if (!empty($lessons)) {
|
||||
$lesson_url = get_permalink($lessons[0]);
|
||||
return $lesson_url ? $lesson_url : $course_url;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to older method
|
||||
if (function_exists('learndash_get_course_lessons_list')) {
|
||||
$lessons = learndash_get_course_lessons_list($course_id);
|
||||
if (!empty($lessons) && is_array($lessons)) {
|
||||
$first_lesson = reset($lessons);
|
||||
if (isset($first_lesson['post']->ID)) {
|
||||
$lesson_url = get_permalink($first_lesson['post']->ID);
|
||||
return $lesson_url ? $lesson_url : $course_url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $course_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize multiple HTML classes
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param string $classes Space-separated list of class names
|
||||
* @return string Sanitized space-separated list of class names
|
||||
*/
|
||||
function ldsb_sanitize_html_classes($classes) {
|
||||
if (empty($classes)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Split by spaces and sanitize each class individually
|
||||
$classes_array = explode(' ', $classes);
|
||||
$sanitized_classes = array();
|
||||
|
||||
foreach ($classes_array as $class) {
|
||||
$class = trim($class);
|
||||
if (!empty($class)) {
|
||||
$sanitized = sanitize_html_class($class);
|
||||
if (!empty($sanitized)) {
|
||||
$sanitized_classes[] = $sanitized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return implode(' ', $sanitized_classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check user access with compatibility
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param int $course_id The course ID to check access for
|
||||
* @param int|null $user_id The user ID to check, defaults to current user
|
||||
* @return bool True if user has access, false otherwise
|
||||
*/
|
||||
function ldsb_check_user_access($course_id, $user_id = null) {
|
||||
if (null === $user_id) {
|
||||
$user_id = get_current_user_id();
|
||||
}
|
||||
|
||||
// Try newer method first (LearnDash 3.0+)
|
||||
if (function_exists('sfwd_lms_has_access')) {
|
||||
return sfwd_lms_has_access($course_id, $user_id);
|
||||
}
|
||||
|
||||
// Fallback for older versions
|
||||
if (function_exists('ld_course_check_user_access')) {
|
||||
return ld_course_check_user_access($course_id, $user_id);
|
||||
}
|
||||
|
||||
// Last resort - check if user is logged in
|
||||
return is_user_logged_in();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first course URL from a group
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param int $group_id The group ID
|
||||
* @return string|false The first course/lesson URL or group URL, false on failure
|
||||
*/
|
||||
function ldsb_get_first_group_course_url($group_id) {
|
||||
// Get group courses
|
||||
$group_courses = array();
|
||||
|
||||
// Try LearnDash 3.2+ method
|
||||
if (function_exists('learndash_group_enrolled_courses')) {
|
||||
$group_courses = learndash_group_enrolled_courses($group_id);
|
||||
} elseif (function_exists('learndash_get_group_enrolled_courses')) {
|
||||
$group_courses = learndash_get_group_enrolled_courses($group_id);
|
||||
} else {
|
||||
// Fallback to direct meta query
|
||||
$group_courses = get_post_meta($group_id, 'learndash_group_enrolled_courses', true);
|
||||
if (!is_array($group_courses)) {
|
||||
$group_courses = array();
|
||||
}
|
||||
}
|
||||
|
||||
// If we have courses, get the first one
|
||||
if (!empty($group_courses)) {
|
||||
$first_course_id = is_array($group_courses) ? reset($group_courses) : $group_courses;
|
||||
|
||||
// Check if it's a valid course
|
||||
if (get_post_type($first_course_id) === 'sfwd-courses') {
|
||||
// Try to get first lesson of this course
|
||||
$course_url = ldsb_get_first_lesson_url($first_course_id);
|
||||
if ($course_url) {
|
||||
return $course_url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to group URL
|
||||
$group_url = get_permalink($group_id);
|
||||
return $group_url ? $group_url : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register shortcode for the Start Group Work button
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param array $atts Shortcode attributes
|
||||
* @return string Button HTML or empty comment
|
||||
*/
|
||||
function ldsb_start_group_shortcode($atts) {
|
||||
// Verify LearnDash is active
|
||||
if (!defined('LEARNDASH_VERSION')) {
|
||||
return '<!-- LearnDash not active -->';
|
||||
}
|
||||
|
||||
// Parse and sanitize attributes
|
||||
$atts = shortcode_atts(array(
|
||||
'group_id' => '',
|
||||
'text' => __('Start First Course', 'learndash-start-button'),
|
||||
'new_tab' => 'no',
|
||||
'class' => '',
|
||||
'alignment' => ''
|
||||
), $atts, 'learndash_start_group');
|
||||
|
||||
// Sanitize inputs
|
||||
$group_id = !empty($atts['group_id']) ? absint($atts['group_id']) : get_the_ID();
|
||||
$button_text = sanitize_text_field($atts['text']);
|
||||
$new_tab = in_array($atts['new_tab'], array('yes', 'true', '1'), true);
|
||||
$custom_class = ldsb_sanitize_html_classes($atts['class']);
|
||||
$alignment = !empty($atts['alignment']) ? sanitize_key($atts['alignment']) : '';
|
||||
|
||||
// Validate group exists and is correct post type
|
||||
$group_post = get_post($group_id);
|
||||
if (!$group_post || get_post_type($group_post) !== 'groups') {
|
||||
return '<!-- Invalid group ID or not a group page -->';
|
||||
}
|
||||
|
||||
// Get the first course URL from the group
|
||||
$course_url = ldsb_get_first_group_course_url($group_id);
|
||||
|
||||
// If we can't get a valid URL, return empty
|
||||
if (!$course_url) {
|
||||
return '<!-- Could not generate valid URL for group -->';
|
||||
}
|
||||
|
||||
// Determine button text - SIMPLIFIED VERSION
|
||||
$access_text = esc_html($button_text); // Default text for everyone
|
||||
|
||||
// ONLY override for logged-out users
|
||||
if (!is_user_logged_in()) {
|
||||
$access_text = __('Login to Start', 'learndash-start-button');
|
||||
$course_url = wp_login_url($course_url);
|
||||
}
|
||||
// Admins and all logged-in users see the default button text
|
||||
// No "Join Group to Start" text anywhere!
|
||||
|
||||
// Build wrapper classes
|
||||
$wrapper_classes = array('ldsb-button-wrapper');
|
||||
if ($alignment) {
|
||||
$wrapper_classes[] = 'align-' . $alignment;
|
||||
}
|
||||
if ($custom_class) {
|
||||
$wrapper_classes[] = $custom_class;
|
||||
}
|
||||
$wrapper_class_string = implode(' ', $wrapper_classes);
|
||||
|
||||
// Build link attributes
|
||||
$link_attrs = array(
|
||||
'href' => esc_url($course_url),
|
||||
'class' => 'ldsb-start-button ldsb-group-button',
|
||||
'role' => 'button',
|
||||
'data-group-id' => $group_id
|
||||
);
|
||||
|
||||
if ($new_tab) {
|
||||
$link_attrs['target'] = '_blank';
|
||||
$link_attrs['rel'] = 'noopener noreferrer';
|
||||
}
|
||||
|
||||
// Build attributes string
|
||||
$attrs_string = '';
|
||||
foreach ($link_attrs as $key => $value) {
|
||||
$attrs_string .= sprintf(' %s="%s"', $key, esc_attr($value));
|
||||
}
|
||||
|
||||
// Build the button HTML
|
||||
$button_html = sprintf(
|
||||
'<div class="%s">
|
||||
<a%s>
|
||||
<span class="ldsb-button-text">%s</span>
|
||||
<svg class="ldsb-button-arrow" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||
<path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>',
|
||||
esc_attr($wrapper_class_string),
|
||||
$attrs_string,
|
||||
$access_text
|
||||
);
|
||||
|
||||
// Allow filtering of output
|
||||
return apply_filters('ldsb_group_button_html', $button_html, $atts);
|
||||
}
|
||||
add_shortcode('learndash_start_group', 'ldsb_start_group_shortcode');
|
||||
|
||||
/**
|
||||
* Register shortcode for the Start Now button
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param array $atts Shortcode attributes
|
||||
* @return string Button HTML or empty comment
|
||||
*/
|
||||
function ldsb_start_button_shortcode($atts) {
|
||||
// Verify LearnDash is active
|
||||
if (!defined('LEARNDASH_VERSION')) {
|
||||
return '<!-- LearnDash not active -->';
|
||||
}
|
||||
|
||||
// Parse and sanitize attributes
|
||||
$atts = shortcode_atts(array(
|
||||
'course_id' => '',
|
||||
'text' => __('Start Course', 'learndash-start-button'),
|
||||
'new_tab' => 'no',
|
||||
'class' => '',
|
||||
'alignment' => ''
|
||||
), $atts, 'learndash_start_button');
|
||||
|
||||
// Sanitize inputs
|
||||
$course_id = !empty($atts['course_id']) ? absint($atts['course_id']) : get_the_ID();
|
||||
$button_text = sanitize_text_field($atts['text']);
|
||||
$new_tab = in_array($atts['new_tab'], array('yes', 'true', '1'), true);
|
||||
$custom_class = ldsb_sanitize_html_classes($atts['class']);
|
||||
$alignment = !empty($atts['alignment']) ? sanitize_key($atts['alignment']) : '';
|
||||
|
||||
// Validate course exists and get post type
|
||||
$course_post = get_post($course_id);
|
||||
if (!$course_post) {
|
||||
return '<!-- Invalid course ID -->';
|
||||
}
|
||||
|
||||
// Get proper course ID if we're on a lesson/topic
|
||||
$course_post_type = get_post_type($course_post);
|
||||
if ($course_post_type !== 'sfwd-courses') {
|
||||
if (function_exists('learndash_get_course_id')) {
|
||||
$course_id = learndash_get_course_id($course_id);
|
||||
if (!$course_id) {
|
||||
return '<!-- No associated course found -->';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the course URL
|
||||
$course_url = ldsb_get_first_lesson_url($course_id);
|
||||
|
||||
// If we can't get a valid URL, return empty
|
||||
if (!$course_url) {
|
||||
return '<!-- Could not generate valid URL for course -->';
|
||||
}
|
||||
|
||||
// Check user access
|
||||
$user_id = get_current_user_id();
|
||||
$has_access = ldsb_check_user_access($course_id, $user_id);
|
||||
$access_text = esc_html($button_text);
|
||||
|
||||
if (!$has_access && !is_user_logged_in()) {
|
||||
$access_text = __('Login to Start', 'learndash-start-button');
|
||||
$course_url = wp_login_url($course_url);
|
||||
} elseif (!$has_access) {
|
||||
$access_text = __('Enroll to Start', 'learndash-start-button');
|
||||
}
|
||||
|
||||
// Build wrapper classes
|
||||
$wrapper_classes = array('ldsb-button-wrapper');
|
||||
if ($alignment) {
|
||||
$wrapper_classes[] = 'align-' . $alignment;
|
||||
}
|
||||
if ($custom_class) {
|
||||
$wrapper_classes[] = $custom_class;
|
||||
}
|
||||
$wrapper_class_string = implode(' ', $wrapper_classes);
|
||||
|
||||
// Build link attributes
|
||||
$link_attrs = array(
|
||||
'href' => esc_url($course_url),
|
||||
'class' => 'ldsb-start-button',
|
||||
'role' => 'button',
|
||||
'data-course-id' => $course_id
|
||||
);
|
||||
|
||||
if ($new_tab) {
|
||||
$link_attrs['target'] = '_blank';
|
||||
$link_attrs['rel'] = 'noopener noreferrer';
|
||||
}
|
||||
|
||||
// Build attributes string
|
||||
$attrs_string = '';
|
||||
foreach ($link_attrs as $key => $value) {
|
||||
$attrs_string .= sprintf(' %s="%s"', $key, esc_attr($value));
|
||||
}
|
||||
|
||||
// Build the button HTML
|
||||
$button_html = sprintf(
|
||||
'<div class="%s">
|
||||
<a%s>
|
||||
<span class="ldsb-button-text">%s</span>
|
||||
<svg class="ldsb-button-arrow" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||
<path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>',
|
||||
esc_attr($wrapper_class_string),
|
||||
$attrs_string,
|
||||
$access_text
|
||||
);
|
||||
|
||||
// Allow filtering of output
|
||||
return apply_filters('ldsb_button_html', $button_html, $atts);
|
||||
}
|
||||
add_shortcode('learndash_start_button', 'ldsb_start_button_shortcode');
|
||||
|
||||
/**
|
||||
* Register Gutenberg blocks
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
function ldsb_register_blocks() {
|
||||
// Check if Gutenberg is available
|
||||
if (!function_exists('register_block_type')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register block editor script
|
||||
wp_register_script(
|
||||
'ldsb-block-editor',
|
||||
LDSB_PLUGIN_URL . 'assets/js/block.js',
|
||||
array('wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-data', 'wp-i18n'),
|
||||
LDSB_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
// Add translation support
|
||||
wp_set_script_translations('ldsb-block-editor', 'learndash-start-button');
|
||||
|
||||
// Register block editor styles
|
||||
wp_register_style(
|
||||
'ldsb-block-editor-style',
|
||||
LDSB_PLUGIN_URL . 'assets/css/editor.css',
|
||||
array('wp-edit-blocks'),
|
||||
LDSB_VERSION
|
||||
);
|
||||
|
||||
// Register the Course Start button block
|
||||
register_block_type('ldsb/start-button', array(
|
||||
'editor_script' => 'ldsb-block-editor',
|
||||
'editor_style' => 'ldsb-block-editor-style',
|
||||
'render_callback' => 'ldsb_render_block',
|
||||
'attributes' => array(
|
||||
'courseId' => array(
|
||||
'type' => 'number',
|
||||
'default' => 0
|
||||
),
|
||||
'buttonText' => array(
|
||||
'type' => 'string',
|
||||
'default' => __('Start Course', 'learndash-start-button')
|
||||
),
|
||||
'newTab' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => false
|
||||
),
|
||||
'alignment' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'left',
|
||||
'enum' => array('left', 'center', 'right')
|
||||
)
|
||||
),
|
||||
'supports' => array(
|
||||
'align' => false, // We handle alignment internally
|
||||
'className' => true,
|
||||
'html' => false
|
||||
)
|
||||
));
|
||||
|
||||
// Register the Group Start button block
|
||||
register_block_type('ldsb/start-group', array(
|
||||
'editor_script' => 'ldsb-block-editor',
|
||||
'editor_style' => 'ldsb-block-editor-style',
|
||||
'render_callback' => 'ldsb_render_group_block',
|
||||
'attributes' => array(
|
||||
'groupId' => array(
|
||||
'type' => 'number',
|
||||
'default' => 0
|
||||
),
|
||||
'buttonText' => array(
|
||||
'type' => 'string',
|
||||
'default' => __('Start First Course', 'learndash-start-button')
|
||||
),
|
||||
'newTab' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => false
|
||||
),
|
||||
'alignment' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'left',
|
||||
'enum' => array('left', 'center', 'right')
|
||||
)
|
||||
),
|
||||
'supports' => array(
|
||||
'align' => false,
|
||||
'className' => true,
|
||||
'html' => false
|
||||
)
|
||||
));
|
||||
}
|
||||
add_action('init', 'ldsb_register_blocks');
|
||||
|
||||
/**
|
||||
* Render block callback
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param array $attributes Block attributes
|
||||
* @return string Block HTML output
|
||||
*/
|
||||
function ldsb_render_block($attributes) {
|
||||
// Sanitize attributes
|
||||
$course_id = isset($attributes['courseId']) ? absint($attributes['courseId']) : 0;
|
||||
$button_text = isset($attributes['buttonText']) ? sanitize_text_field($attributes['buttonText']) : __('Start Course', 'learndash-start-button');
|
||||
$new_tab = isset($attributes['newTab']) && $attributes['newTab'] ? 'yes' : 'no';
|
||||
$alignment = isset($attributes['alignment']) ? sanitize_key($attributes['alignment']) : 'left';
|
||||
|
||||
// Pass alignment to shortcode
|
||||
return ldsb_start_button_shortcode(array(
|
||||
'course_id' => $course_id,
|
||||
'text' => $button_text,
|
||||
'new_tab' => $new_tab,
|
||||
'alignment' => $alignment
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Render group block callback
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param array $attributes Block attributes
|
||||
* @return string Block HTML output
|
||||
*/
|
||||
function ldsb_render_group_block($attributes) {
|
||||
// Sanitize attributes
|
||||
$group_id = isset($attributes['groupId']) ? absint($attributes['groupId']) : 0;
|
||||
$button_text = isset($attributes['buttonText']) ? sanitize_text_field($attributes['buttonText']) : __('Start First Course', 'learndash-start-button');
|
||||
$new_tab = isset($attributes['newTab']) && $attributes['newTab'] ? 'yes' : 'no';
|
||||
$alignment = isset($attributes['alignment']) ? sanitize_key($attributes['alignment']) : 'left';
|
||||
|
||||
// Pass to group shortcode
|
||||
return ldsb_start_group_shortcode(array(
|
||||
'group_id' => $group_id,
|
||||
'text' => $button_text,
|
||||
'new_tab' => $new_tab,
|
||||
'alignment' => $alignment
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin activation hook
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
function ldsb_activate() {
|
||||
// Check minimum requirements
|
||||
if (version_compare(PHP_VERSION, '7.2', '<')) {
|
||||
deactivate_plugins(LDSB_PLUGIN_BASENAME);
|
||||
wp_die(__('This plugin requires PHP 7.2 or higher.', 'learndash-start-button'));
|
||||
}
|
||||
|
||||
// Set default options
|
||||
add_option('ldsb_version', LDSB_VERSION);
|
||||
|
||||
// Note: flush_rewrite_rules() removed - this plugin doesn't register custom post types or rewrite rules
|
||||
}
|
||||
register_activation_hook(__FILE__, 'ldsb_activate');
|
||||
|
||||
/**
|
||||
* Plugin deactivation hook
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
function ldsb_deactivate() {
|
||||
// Note: No cleanup needed on deactivation
|
||||
// flush_rewrite_rules() should NOT be called on deactivation per WordPress best practices
|
||||
}
|
||||
register_deactivation_hook(__FILE__, 'ldsb_deactivate');
|
||||
|
||||
/**
|
||||
* Load plugin textdomain
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
function ldsb_load_textdomain() {
|
||||
load_plugin_textdomain(
|
||||
'learndash-start-button',
|
||||
false,
|
||||
dirname(LDSB_PLUGIN_BASENAME) . '/languages'
|
||||
);
|
||||
}
|
||||
add_action('plugins_loaded', 'ldsb_load_textdomain');
|
||||
|
||||
// End of file - no closing PHP tag to prevent whitespace issues
|
||||
32
native/wordpress/learndash-start-button/uninstall.php
Normal file
32
native/wordpress/learndash-start-button/uninstall.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* LearnDash Start Now Button - Uninstall
|
||||
*
|
||||
* Handles plugin cleanup when deleted through WordPress admin
|
||||
*
|
||||
* @package LearnDashStartButton
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// If uninstall not called from WordPress, exit
|
||||
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Clean up options
|
||||
delete_option('ldsb_version');
|
||||
|
||||
// Clean up any transients (if you add any in the future)
|
||||
delete_transient('ldsb_courses_cache');
|
||||
|
||||
// Clean up user meta if any (currently none)
|
||||
// delete_metadata('user', 0, 'ldsb_user_preference', '', true);
|
||||
|
||||
// Clean up post meta if any (currently none)
|
||||
// delete_post_meta_by_key('_ldsb_button_override');
|
||||
|
||||
// Flush rewrite rules
|
||||
flush_rewrite_rules();
|
||||
|
||||
// Note: We don't delete the block from posts as that could break content
|
||||
// The blocks will gracefully degrade to showing nothing if plugin is removed
|
||||
Loading…
Add table
Add a link
Reference in a new issue