{"id":44003624,"url":"https://github.com/j7-dev/wp-power-course","last_synced_at":"2026-04-02T14:50:43.851Z","repository":{"id":235145531,"uuid":"786632020","full_name":"j7-dev/wp-power-course","owner":"j7-dev","description":null,"archived":false,"fork":false,"pushed_at":"2025-11-20T03:34:03.000Z","size":7838,"stargazers_count":4,"open_issues_count":21,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-20T05:26:17.466Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/j7-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-04-15T02:09:17.000Z","updated_at":"2025-11-20T03:34:07.000Z","dependencies_parsed_at":"2024-04-22T12:15:06.063Z","dependency_job_id":"499306c7-2942-4647-8832-ddce0c4f4daa","html_url":"https://github.com/j7-dev/wp-power-course","commit_stats":null,"previous_names":["j7-dev/wp-power-course"],"tags_count":203,"template":false,"template_full_name":null,"purl":"pkg:github/j7-dev/wp-power-course","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j7-dev%2Fwp-power-course","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j7-dev%2Fwp-power-course/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j7-dev%2Fwp-power-course/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j7-dev%2Fwp-power-course/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/j7-dev","download_url":"https://codeload.github.com/j7-dev/wp-power-course/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j7-dev%2Fwp-power-course/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29194589,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T12:38:28.597Z","status":"ssl_error","status_checked_at":"2026-02-07T12:38:23.888Z","response_time":63,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-07T13:06:30.678Z","updated_at":"2026-04-02T14:50:43.844Z","avatar_url":"https://github.com/j7-dev.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Power Course — WordPress LMS Plugin\n\n[繁體中文](./README.zh-TW.md) | English\n\n[![Version](https://img.shields.io/badge/version-1.1.0--rc1-blue)](https://github.com/j7-dev/wp-power-course/releases)\n[![PHP](https://img.shields.io/badge/PHP-8.0%2B-purple)](https://www.php.net/)\n[![WordPress](https://img.shields.io/badge/WordPress-5.7%2B-blue)](https://wordpress.org/)\n[![WooCommerce](https://img.shields.io/badge/WooCommerce-7.6.0%2B-purple)](https://woocommerce.com/)\n[![License](https://img.shields.io/badge/license-GPL%20v2-green)](./LICENSE)\n\n\u003e A full-featured LMS plugin for WordPress + WooCommerce — sell and manage online courses with a modern React admin interface.\n\n---\n\n## Overview\n\nPower Course transforms WooCommerce products into online courses with hierarchical chapters, video streaming, progress tracking, and automated email workflows — all managed through a React SPA admin dashboard backed by a RESTful API.\n\n---\n\n## Features\n\n### Course Management\n- Create, update, delete, and duplicate courses\n- Courses are built on WooCommerce products — pricing, stock, and checkout flow are handled natively\n- Filter and search course listings\n- Set course visibility and launch schedule (scheduled start date triggers automatic notifications)\n\n### Chapter Management\n- Hierarchical chapter / unit structure with unlimited nesting\n- Drag-and-drop reordering (sort chapters via API)\n- Upload and delete subtitle files (`.srt`) per chapter\n- Per-chapter completion toggle tracked per student\n\n### Student Management\n- Enroll students into a course manually or in bulk (CSV import)\n- Remove student course access\n- Update individual student expiry dates\n- View student list with search and pagination\n- Export student list to CSV\n- View per-student activity logs (chapter visits, completions, access events)\n\n### Progress Tracking\n- Toggle chapter completion status per student\n- Course progress calculated as a percentage (0–100%) based on completed chapters\n- Triggers `power_course_course_finished` action when 100% is reached\n\n### Access Control\n| Type | Description |\n|------|-------------|\n| Unlimited | No expiry |\n| Fixed duration | N days from enrollment |\n| Specific date | Access until a set date |\n| Subscription | Follows WooCommerce Subscription lifecycle |\n\n### Bundle Products (Sales Plans)\n- Group multiple products into a bundle that grants access to linked courses on purchase\n- Display bundle item quantities in the product listing\n- Bundles cannot contain other bundles\n\n### Automated Email (PowerEmail)\n- Drag-and-drop MJML-based email builder\n- 5 trigger events:\n\n| Trigger | When Fired |\n|---------|-----------|\n| `course_granted` | Student gains course access |\n| `course_finish` | Student reaches 100% completion |\n| `course_launch` | Scheduled course launch date is reached |\n| `chapter_enter` | Student first enters a chapter |\n| `chapter_finish` | Student marks a chapter as complete |\n\n- Variable replacement: `{user.display_name}`, `{user.email}`, `{course.title}`, `{chapter.title}`, and more\n- Create, update, and delete email templates\n- Automatic email send history stored in database\n\n### WooCommerce Integration\n- Auto-activate course access when an order reaches the configured status (default: `completed`)\n- Prevent guest checkout for course products\n- Bind multiple courses to a single WooCommerce product\n- Scheduled course start notifications dispatched via Action Scheduler\n\n### Teacher Management\n- Assign one or more instructors to a course\n- Dedicated teacher management interface in the admin panel\n\n### Analytics \u0026 Reports\n- Revenue reports per course / date range\n- Course completion rate statistics\n- Student activity log with filterable event types\n\n### Media \u0026 Watermarking\n- Upload media files (video, images, PDFs) through the admin\n- Dynamic video watermark overlay (user info — display name, email, etc.)\n- PDF watermark support\n- Configurable watermark count and template text\n\n### Video Playback\n- **Bunny Stream** (HLS adaptive streaming) — primary CDN\n- **YouTube** embed\n- **Vimeo** embed\n- Custom embed code support\n- Sticky video player and tab navigation on mobile\n\n### Subtitles\n- Upload `.srt` subtitle files per chapter\n- Delete subtitles\n- Default empty subtitle option (no subtitle selected by default)\n\n---\n\n## Requirements\n\n| Dependency | Minimum Version | Source |\n|-----------|----------------|--------|\n| WordPress | 5.7 | [wordpress.org](https://wordpress.org/) |\n| PHP | 8.0 | |\n| WooCommerce | 7.6.0 | [wordpress.org/plugins/woocommerce](https://wordpress.org/plugins/woocommerce/) |\n| [Powerhouse](https://github.com/j7-dev/wp-powerhouse) | 3.3.41 | GitHub |\n\n**Optional:**\n- WooCommerce Subscriptions — required for subscription-based access control\n\n---\n\n## Installation\n\n### Production\n\n1. Download the latest `.zip` from [GitHub Releases](https://github.com/j7-dev/wp-power-course/releases)\n2. In WordPress Admin go to **Plugins → Add New → Upload Plugin**\n3. Install and activate **WooCommerce** and **Powerhouse** first\n4. Install and activate **Power Course**\n5. The plugin automatically creates 4 required database tables on activation\n\n### Development\n\n```bash\n# PHP dependencies\ncomposer install\n\n# JS dependencies\npnpm install\n\n# Start Vite dev server (port 5174)\npnpm run dev\n\n# Production build\npnpm run build\n```\n\n---\n\n## Architecture\n\n### Tech Stack\n\n| Layer | Technology |\n|-------|-----------|\n| Backend language | PHP 8.0+, `declare(strict_types=1)` |\n| Backend framework | WordPress, WooCommerce 7.6.0+, Powerhouse 3.3.41+ |\n| PHP namespace | `J7\\PowerCourse` (PSR-4: `inc/classes/`, `inc/src/`) |\n| Frontend language | TypeScript 5.5 (strict mode) |\n| Frontend framework | React 18, Refine.dev 4.x, Ant Design 5.x |\n| State management | Jotai (UI state), TanStack Query 4.x (server state) |\n| Build tool | Vite + @kucrut/vite-for-wp |\n| Video player | VidStack, hls.js, Bunny CDN |\n| Email editor | j7-easy-email (MJML-based) |\n| Testing | Playwright E2E, PHPUnit |\n| PHP quality | PHPCS (WordPress standards) + PHPStan level 9 |\n| TS quality | ESLint + Prettier |\n\n### Directory Structure\n\n```\npower-course/\n├── plugin.php              # Plugin entry point (Singleton)\n├── inc/                    # PHP backend\n│   ├── classes/            # PSR-4 autoload\n│   │   ├── Api/            # REST API endpoints\n│   │   ├── Resources/      # Domain resources (Course, Chapter, Student…)\n│   │   ├── BundleProduct/  # Bundle / sales plan logic\n│   │   ├── PowerEmail/     # Automated email subsystem\n│   │   └── Utils/          # Utility classes\n│   ├── src/Domain/         # DDD-style: Product Events\n│   └── templates/          # PHP frontend templates\n├── js/src/                 # React admin SPA\n│   ├── pages/admin/        # Admin pages (lazy-loaded)\n│   ├── components/         # Reusable components\n│   ├── hooks/              # Custom React hooks\n│   ├── resources/          # Refine.dev resource definitions\n│   └── types/              # TypeScript type definitions\n├── tests/e2e/              # Playwright E2E tests\n└── specs/                  # Business specification documents\n```\n\n### Custom Database Tables\n\n| Table | Purpose |\n|-------|---------|\n| `{prefix}_pc_avl_coursemeta` | User ↔ Course metadata (expiry, progress) |\n| `{prefix}_pc_avl_chaptermeta` | User ↔ Chapter progress |\n| `{prefix}_pc_email_records` | Automated email send history |\n| `{prefix}_pc_student_logs` | Student activity audit trail |\n\n### Custom Post Type\n\n| CPT | Slug | Description |\n|-----|------|-------------|\n| `pc_chapter` | `classroom` | Course chapters (hierarchical) |\n\n---\n\n## REST API\n\nBase URL: `{site_url}/wp-json/power-course/v2/`\n\n| Endpoint | Methods | Description |\n|----------|---------|-------------|\n| `courses` | GET, POST, DELETE | List / create / bulk-delete courses |\n| `courses/{id}` | GET, POST, DELETE | Get / update / delete a course |\n| `courses/add-students` | POST | Enroll students into a course |\n| `courses/remove-students` | POST | Revoke student course access |\n| `courses/update-students` | POST | Update student expiry dates |\n| `courses/student-logs` | GET | Student activity logs |\n| `chapters` | GET, POST, DELETE | List / create / bulk-delete chapters |\n| `chapters/{id}` | POST | Update a chapter |\n| `chapters/sort` | POST | Reorder chapters |\n| `chapters/{id}/subtitles` | POST, DELETE | Upload / delete subtitle file |\n| `toggle-finish-chapters/{id}` | POST | Toggle chapter completion |\n| `products` | GET | List WooCommerce products |\n| `bundle-products` | GET, POST | Manage bundle products |\n| `teachers` | GET, POST | Manage teacher assignments |\n| `options` | GET, POST | Plugin settings |\n| `reports/revenue` | GET | Revenue analytics |\n| `comments` | GET, POST | Chapter comments |\n| `media` | POST | Upload media files |\n\nFull OpenAPI 3.0.3 specification: [`specs/api/api.yml`](./specs/api/api.yml)\n\n---\n\n## WordPress Hooks\n\n### Actions\n\n```php\n// After course access is granted to a student\nadd_action(\n    'power_course_after_add_student_to_course',\n    function( int $user_id, int $course_id, int|string $expire_date, ?\\WC_Order $order ) {\n        // send custom notification, award points, etc.\n    },\n    10, 4\n);\n\n// When a student reaches 100% course completion\nadd_action(\n    'power_course_course_finished',\n    function( int $course_id, int $user_id ) {\n        // issue certificate, etc.\n    },\n    10, 2\n);\n\n// Before course / chapter meta is saved via REST API\nadd_action(\n    'power_course_before_update_product_meta',\n    function( \\WC_Product $product, array $meta_data ) {\n        // validate or modify meta data before save\n    },\n    10, 2\n);\n```\n\n### Granting Course Access Programmatically\n\n```php\nuse J7\\PowerCourse\\Resources\\Course\\LifeCycle;\n\n// Always dispatch the action — never call the underlying function directly\ndo_action(\n    LifeCycle::ADD_STUDENT_TO_COURSE_ACTION,\n    $user_id,      // int   — WordPress user ID\n    $course_id,    // int   — WooCommerce product ID\n    $expire_date,  // 0 = unlimited | Unix timestamp | 'subscription_123'\n    $order         // \\WC_Order|null\n);\n```\n\n### Utility Functions\n\n```php\nuse J7\\PowerCourse\\Utils\\Course as CourseUtils;\n\nCourseUtils::is_course_product( $product );          // bool — is this a course?\nCourseUtils::is_avl( $course_id, $user_id );         // bool — does user have access?\nCourseUtils::is_course_ready( $product );             // bool — has it launched?\nCourseUtils::is_expired( $product, $user_id );       // bool — has access expired?\nCourseUtils::get_course_progress( $product, $user_id ); // float 0–100\n```\n\n---\n\n## Plugin Settings\n\nConfigure at **Power Course → Settings** or via `POST /wp-json/power-course/v2/options`.\n\n| Setting | Default | Description |\n|---------|---------|-------------|\n| `course_access_trigger` | `completed` | WC order status that grants access |\n| `hide_myaccount_courses` | `no` | Hide courses tab in WC My Account |\n| `fix_video_and_tabs_mobile` | `no` | Enable sticky video / tabs on mobile |\n| `pc_watermark_qty` | `0` | Video watermark count (0 = disabled) |\n| `pc_watermark_text` | `用戶 {display_name}...` | Watermark label template |\n| `pc_pdf_watermark_qty` | `0` | PDF watermark count |\n| `hide_courses_in_main_query` | `no` | Exclude courses from main WP query |\n\n**Bunny Stream CDN** credentials (library ID, CDN hostname, API key) are configured in **Powerhouse → Settings**, not Power Course.\n\n---\n\n## Development\n\n### Commands\n\n```bash\n# Development\npnpm run dev              # Vite dev server (http://localhost:5174)\npnpm run build            # Production JS build\npnpm run build:wp         # WordPress-optimized build\n\n# Quality checks\npnpm run lint:php         # PHPCS + PHPStan\npnpm run lint:ts          # ESLint\npnpm run format           # Prettier-ESLint format\ncomposer run phpstan      # PHPStan static analysis (level 9)\n\n# Testing\ncomposer run test             # PHPUnit\npnpm run test:e2e             # All Playwright E2E tests\npnpm run test:e2e:admin       # Admin-side E2E\npnpm run test:e2e:frontend    # Frontend E2E\npnpm run test:e2e:integration # Integration E2E\n\n# Release\npnpm run release          # Bump patch version + build + release\npnpm run release:minor    # Bump minor version\npnpm run release:major    # Bump major version\npnpm run zip              # Create distributable plugin zip\npnpm run sync:version     # Sync version: package.json → plugin.php\n```\n\n### Code Standards\n\n- **PHP**: WordPress Coding Standards (WPCS), PHPStan level 9 (`phpstan.neon`)\n- **TypeScript**: ESLint with strict mode\n- **Formatting**: Prettier (tabs, single quotes, no semicolons)\n- **Commits**: Conventional Commits (`feat:`, `fix:`, `chore:`, etc.)\n\n---\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch: `git checkout -b feat/my-feature`\n3. Follow the coding standards above\n4. Ensure all tests pass: `pnpm run test:e2e` and `composer run test`\n5. Open a Pull Request against `master`\n\n---\n\n## License\n\nGPL v2 or later — see [LICENSE](./LICENSE) for details.\n\n---\n\n## Links\n\n- [GitHub Repository](https://github.com/j7-dev/wp-power-course)\n- [Author](https://github.com/j7-dev)\n- [Powerhouse Plugin](https://github.com/j7-dev/wp-powerhouse)\n- [API Specification](./specs/api/api.yml)\n- [WordPress Developer Reference](https://developer.wordpress.org/reference/)\n- [WooCommerce Code Reference](https://woocommerce.github.io/code-reference/)\n- [Refine.dev Documentation](https://refine.dev/docs/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fj7-dev%2Fwp-power-course","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fj7-dev%2Fwp-power-course","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fj7-dev%2Fwp-power-course/lists"}