assets
3 weeks ago
src
2 days ago
AGENTS.md
2 days ago
CHANGELOG.md
2 days ago
LICENSE
5 years ago
index.php
5 years ago
load.php
2 days ago
start.php
2 months ago
AGENTS.md
191 lines
| 1 | # ThemeIsle SDK — Agent Reference |
| 2 | |
| 3 | > Quick-reference guide for AI agents working on this codebase. |
| 4 | |
| 5 | ## What This Is |
| 6 | |
| 7 | A shared WordPress library bundled into Themeisle plugins and themes. It provides common features (licensing, analytics, notifications, promotions, etc.) so each product doesn't reimplement them. Multiple products may bundle different versions; only the highest version ever loads. |
| 8 | |
| 9 | ## Directory Map |
| 10 | |
| 11 | ``` |
| 12 | themeisle-sdk-main/ |
| 13 | ├── load.php Entry point bundled by each product. Handles version arbitration. |
| 14 | ├── start.php Bootstrap: requires all class files, calls Loader::init(). |
| 15 | ├── src/ |
| 16 | │ ├── Loader.php Singleton. Owns $products, $available_modules, $labels. |
| 17 | │ ├── Product.php Model for a registered plugin/theme. Reads file headers. |
| 18 | │ ├── Common/ |
| 19 | │ │ ├── Abstract_module.php Base class every module extends. |
| 20 | │ │ └── Module_factory.php Instantiates + attaches modules to products. |
| 21 | │ └── Modules/ One file per feature module (18 total). |
| 22 | ├── tests/ PHPUnit tests. One file per module. |
| 23 | ├── docs/ Integration guides. One file per feature. |
| 24 | └── assets/ Compiled JS/CSS for SDK UI components. |
| 25 | ``` |
| 26 | |
| 27 | ## Key Concepts |
| 28 | |
| 29 | ### How Products Register |
| 30 | Products add their base file to the `themeisle_sdk_products` filter — that is the *only* required step: |
| 31 | |
| 32 | ```php |
| 33 | add_filter( 'themeisle_sdk_products', function( $products ) { |
| 34 | $products[] = __FILE__; |
| 35 | return $products; |
| 36 | } ); |
| 37 | ``` |
| 38 | |
| 39 | ### Product File Headers |
| 40 | The SDK reads WordPress file headers to configure itself per product: |
| 41 | |
| 42 | ``` |
| 43 | WordPress Available: yes # yes = on WP.org (free). no = premium only. |
| 44 | Requires License: yes # yes = activates the Licenser module. |
| 45 | Pro Slug: neve-pro # Slug of the companion pro plugin. |
| 46 | ``` |
| 47 | |
| 48 | ### Module Loading Contract |
| 49 | Each module in `src/Modules/` extends `Abstract_Module` and implements: |
| 50 | - `can_load( $product ) : bool` — Should this module run for this product? |
| 51 | - `load( $product ) : self` — Register WordPress hooks. |
| 52 | |
| 53 | `Module_Factory::attach()` calls both methods for every registered module/product pair. |
| 54 | |
| 55 | ### Labels (UI Strings) |
| 56 | All UI strings are in `Loader::$labels` (see [](src/Loader.phpsrc/Loader.php](src/Loader.php](src/Loader.php) lines 73–328). Products and plugins override them via: |
| 57 | |
| 58 | ```php |
| 59 | add_filter( 'themeisle_sdk_labels', function( $labels ) { |
| 60 | $labels['review']['notice'] = __( 'Custom message', 'text-domain' ); |
| 61 | return $labels; |
| 62 | } ); |
| 63 | ``` |
| 64 | |
| 65 | The merge logic ensures the first real translation wins; later callbacks cannot overwrite already-translated values. |
| 66 | |
| 67 | ## All 18 Modules |
| 68 | |
| 69 | | Module | File | Loads when | Doc | |
| 70 | |--------|------|-----------|-----| |
| 71 | | `licenser` | `Licenser.php` | `Requires License: yes` in header | [](docs/LICENSER.mddocs/LICENSER.md](docs/LICENSER.md](docs/LICENSER.md) | |
| 72 | | `logger` | `Logger.php` | Always (filterable) | [](docs/LOGGER.mddocs/LOGGER.md](docs/LOGGER.md](docs/LOGGER.md) | |
| 73 | | `notification` | `Notification.php` | Installed >100h, admin user | [](docs/NOTIFICATIONS.mddocs/NOTIFICATIONS.md](docs/NOTIFICATIONS.md](docs/NOTIFICATIONS.md) | |
| 74 | | `review` | `Review.php` | `WordPress Available: yes`, not partner | [](docs/REVIEW.mddocs/REVIEW.md](docs/REVIEW.md](docs/REVIEW.md) | |
| 75 | | `promotions` | `Promotions.php` | Not partner, not recently dismissed | [](docs/PROMOTIONS.mddocs/PROMOTIONS.md](docs/PROMOTIONS.md](docs/PROMOTIONS.md) | |
| 76 | | `rollback` | `Rollback.php` | Always | [](docs/ROLLBACK.mddocs/ROLLBACK.md](docs/ROLLBACK.md](docs/ROLLBACK.md) | |
| 77 | | `uninstall_feedback` | `Uninstall_feedback.php` | Always | [](docs/UNINSTALL-FEEDBACK.mddocs/UNINSTALL-FEEDBACK.md](docs/UNINSTALL-FEEDBACK.md](docs/UNINSTALL-FEEDBACK.md) | |
| 78 | | `about_us` | `About_us.php` | `{key}_about_us_metadata` filter returns data | [](docs/ABOUT-US.mddocs/ABOUT-US.md](docs/ABOUT-US.md](docs/ABOUT-US.md) | |
| 79 | | `float_widget` | `Float_widget.php` | `{key}_float_widget_metadata` filter returns data | [](docs/FLOAT-WIDGET.mddocs/FLOAT-WIDGET.md](docs/FLOAT-WIDGET.md](docs/FLOAT-WIDGET.md) | |
| 80 | | `announcements` | `Announcements.php` | Not partner | [](docs/ANNOUNCEMENTS.mddocs/ANNOUNCEMENTS.md](docs/ANNOUNCEMENTS.md](docs/ANNOUNCEMENTS.md) | |
| 81 | | `welcome` | `Welcome.php` | `{key}_welcome_metadata` filter returns enabled data | [](docs/WELCOME.mddocs/WELCOME.md](docs/WELCOME.md](docs/WELCOME.md) | |
| 82 | | `compatibilities` | `Compatibilities.php` | Not partner, admin user | [](docs/COMPATIBILITIES.mddocs/COMPATIBILITIES.md](docs/COMPATIBILITIES.md](docs/COMPATIBILITIES.md) | |
| 83 | | `dashboard_widget` | `Dashboard_widget.php` | Not partner | — | |
| 84 | | `featured_plugins` | `Featured_plugins.php` | Always | — | |
| 85 | | `recommendation` | `Recommendation.php` | Always | — | |
| 86 | | `script_loader` | `Script_loader.php` | Always | [](docs/TELEMETRY.mddocs/TELEMETRY.md](docs/TELEMETRY.md](docs/TELEMETRY.md) | |
| 87 | | `translate` | `Translate.php` | Always | — | |
| 88 | | `translations` | `Translations.php` | Always | — | |
| 89 | |
| 90 | ## Common Filter Reference |
| 91 | |
| 92 | | Filter | Purpose | |
| 93 | |--------|---------| |
| 94 | | `themeisle_sdk_products` | Register a product base file | |
| 95 | | `themeisle_sdk_labels` | Override any UI string | |
| 96 | | `themeisle_sdk_modules` | Add custom module names | |
| 97 | | `themeisle_sdk_required_files` | Add custom module PHP files | |
| 98 | | `themeisle_sdk_enable_telemetry` | Enable JS telemetry (return `true`) | |
| 99 | | `themeisle_sdk_disable_telemetry` | Disable all telemetry (return `true`) | |
| 100 | | `themeisle_sdk_hide_notifications` | Suppress all admin notices | |
| 101 | | `themeisle_sdk_is_black_friday_sale` | Force Black Friday banner on/off | |
| 102 | | `themeisle_sdk_promo_debug` | Force promotions to show (dev only) | |
| 103 | | `themeisle_sdk_welcome_debug` | Force welcome notice to show (dev only) | |
| 104 | | `themeisle_sdk_current_date` | Override current date (useful in tests) | |
| 105 | | `{product_key}_about_us_metadata` | Configure About Us page | |
| 106 | | `{product_key}_float_widget_metadata` | Configure floating help widget | |
| 107 | | `{product_key}_welcome_metadata` | Configure welcome/upgrade notice | |
| 108 | | `{product_key}_load_promotions` | Add promotion slugs for this product | |
| 109 | | `{product_key}_dissallowed_promotions` | Block specific promotion slugs | |
| 110 | | `{product_slug}_sdk_enable_logger` | Enable/disable logger for product | |
| 111 | | `{product_slug}_sdk_should_review` | Enable/disable review prompt | |
| 112 | | `{product_key}_enable_licenser` | Enable/disable licenser module | |
| 113 | | `{product_key}_hide_license_field` | Hide license field on settings page | |
| 114 | | `{product_key}_hide_license_notices` | Suppress license admin notices | |
| 115 | | `themeisle_sdk_compatibilities/{slug}` | Declare version compatibility requirements | |
| 116 | | `themesle_sdk_namespace_{md5(basefile)}` | Set product namespace for license filters | |
| 117 | | `themeisle_sdk_license_process_{ns}` | Trigger license activate/deactivate | |
| 118 | | `product_{ns}_license_status` | Read license status | |
| 119 | | `product_{ns}_license_key` | Read license key | |
| 120 | | `product_{ns}_license_plan` | Read license plan/price ID | |
| 121 | | `tsdk_utmify_{content}` | Override UTM params for a URL | |
| 122 | | `tsdk_utmify_url_{content}` | Override final UTM-ified URL | |
| 123 | |
| 124 | ## Common Action Reference |
| 125 | |
| 126 | | Action | Purpose | |
| 127 | |--------|---------| |
| 128 | | `{product_key}_uninstall_feedback_popup_header_after_heading` | Output markup below the uninstall popup heading (`$product`, `$context`) | |
| 129 | |
| 130 | ## Global Helper Functions |
| 131 | |
| 132 | Defined in `load.php`, available everywhere after `init`: |
| 133 | |
| 134 | ```php |
| 135 | tsdk_utmify( $url, $area, $location ) // Append UTM params |
| 136 | tsdk_lstatus( $file ) // License status string |
| 137 | tsdk_lis_valid( $file ) // bool — is license valid? |
| 138 | tsdk_lplan( $file ) // int — license price_id |
| 139 | tsdk_lkey( $file ) // string — license key |
| 140 | tsdk_translate_link( $url, $type, $langs ) // Localize a URL |
| 141 | tsdk_support_link( $file ) // Pre-filled support URL or false |
| 142 | ``` |
| 143 | |
| 144 | ## Options Written by the SDK |
| 145 | |
| 146 | All options use `{product_key}` where key = slug with hyphens replaced by underscores. |
| 147 | |
| 148 | | Option | Content | |
| 149 | |--------|---------| |
| 150 | | `{key}_install` | Unix timestamp of first activation | |
| 151 | | `{key}_version` | Last known product version | |
| 152 | | `{key}_license` | Raw license key (free products) | |
| 153 | | `{key}_license_data` | JSON object from license API | |
| 154 | | `{key}_license_status` | `valid` \| `not_active` \| `active_expired` | |
| 155 | | `{key}_logger_flag` | `yes` \| `no` | |
| 156 | | `themeisle_sdk_notifications` | Notification queue metadata | |
| 157 | | `themeisle_sdk_promotions` | Promotion dismiss timestamps | |
| 158 | | `themeisle_sdk_promotions_{promo}_installed` | Whether a promoted plugin was installed | |
| 159 | |
| 160 | ## API Endpoints |
| 161 | |
| 162 | ``` |
| 163 | https://api.themeisle.com/license/check/{product}/{key}/{url}/{token} |
| 164 | https://api.themeisle.com/license/activate/{product}/{key} |
| 165 | https://api.themeisle.com/license/deactivate/{product}/{key} |
| 166 | https://api.themeisle.com/license/version/{product}/{key}/{version}/{url} |
| 167 | https://api.themeisle.com/license/versions/{product}/{key}/{url}/{version} |
| 168 | https://api.themeisle.com/tracking/log |
| 169 | https://api.themeisle.com/tracking/events |
| 170 | https://api.themeisle.com/tracking/uninstall |
| 171 | ``` |
| 172 | |
| 173 | ## Tests |
| 174 | |
| 175 | ```bash |
| 176 | composer install |
| 177 | ./vendor/bin/phpunit |
| 178 | ``` |
| 179 | |
| 180 | Test files mirror module names: `tests/licenser-test.php`, `tests/loader-test.php`, etc. |
| 181 | Sample products used in tests live in `tests/sample_products/`. |
| 182 | |
| 183 | ## Adding a New Module |
| 184 | |
| 185 | 1. Create `src/Modules/My_Feature.php` extending `Abstract_Module` |
| 186 | 2. Implement `can_load()` and `load()` |
| 187 | 3. Add `'my_feature'` to `$available_modules` in `Loader.php` |
| 188 | 4. Add the file path to the `$files_to_load` array in `start.php` |
| 189 | 5. Add a test in `tests/my-feature-test.php` |
| 190 | 6. Add a doc in `docs/MY-FEATURE.md` |
| 191 |