Changeset 3416646
- Timestamp:
- 12/10/2025 05:43:50 PM (4 months ago)
- Location:
- email-tracker/trunk
- Files:
-
- 224 added
- 7 deleted
- 40 edited
-
.wp-env.json (deleted)
-
assets/build/index.asset.php (modified) (1 diff)
-
assets/build/index.js (modified) (8 diffs)
-
assets/build/index.js.map (modified) (1 diff)
-
assets/build/pro/index.asset.php (modified) (1 diff)
-
assets/build/pro/index.js (modified) (1 diff)
-
assets/package.json (modified) (1 diff)
-
assets/src/index.js (modified) (8 diffs)
-
assets/src/pro/index.js (modified) (1 diff)
-
composer.json (modified) (1 diff)
-
composer.lock (modified) (4 diffs)
-
email-tracker-main.php (modified) (4 diffs)
-
email-tracker.php (modified) (3 diffs)
-
emtr-uninstall.php (modified) (5 diffs)
-
et-admin.php (modified) (3 diffs)
-
libs (deleted)
-
readme.txt (modified) (5 diffs)
-
src/admin/class-email-tracker-admin.php (modified) (2 diffs)
-
src/admin/email-list/class-setup.php (modified) (9 diffs)
-
src/admin/email-list/class-table.php (modified) (21 diffs)
-
src/admin/settings (deleted)
-
src/class-util.php (modified) (4 diffs)
-
src/core/class-chunk-processor.php (modified) (7 diffs)
-
src/core/class-name-space-auto-loader.php (modified) (1 diff)
-
src/integrations/emtr.php (modified) (2 diffs)
-
src/model/class-trackemail.php (modified) (3 diffs)
-
src/newsletter (deleted)
-
track-email.php (modified) (2 diffs)
-
vendor/autoload.php (modified) (1 diff)
-
vendor/composer/ClassLoader.php (modified) (24 diffs)
-
vendor/composer/InstalledVersions.php (modified) (1 diff)
-
vendor/composer/autoload_classmap.php (modified) (1 diff)
-
vendor/composer/autoload_files.php (added)
-
vendor/composer/autoload_namespaces.php (modified) (1 diff)
-
vendor/composer/autoload_psr4.php (modified) (1 diff)
-
vendor/composer/autoload_real.php (modified) (1 diff)
-
vendor/composer/autoload_static.php (modified) (1 diff)
-
vendor/composer/installed.json (modified) (3 diffs)
-
vendor/composer/installed.php (modified) (1 diff)
-
vendor/composer/platform_check.php (modified) (1 diff)
-
vendor/freemius (added)
-
vendor/freemius/wordpress-sdk (added)
-
vendor/freemius/wordpress-sdk/LICENSE.txt (added)
-
vendor/freemius/wordpress-sdk/assets (added)
-
vendor/freemius/wordpress-sdk/assets/css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/account.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/add-ons.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/affiliation.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/checkout.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/clone-resolution.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/common.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/connect.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/debug.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/dialog-boxes.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/gdpr-optin-notice.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/index.php (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/optout.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/admin/plugins.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/customizer.css (added)
-
vendor/freemius/wordpress-sdk/assets/css/index.php (added)
-
vendor/freemius/wordpress-sdk/assets/img (added)
-
vendor/freemius/wordpress-sdk/assets/img/index.php (added)
-
vendor/freemius/wordpress-sdk/assets/img/plugin-icon.png (added)
-
vendor/freemius/wordpress-sdk/assets/img/theme-icon.png (added)
-
vendor/freemius/wordpress-sdk/assets/index.php (added)
-
vendor/freemius/wordpress-sdk/assets/js (added)
-
vendor/freemius/wordpress-sdk/assets/js/index.php (added)
-
vendor/freemius/wordpress-sdk/assets/js/jquery.form.js (added)
-
vendor/freemius/wordpress-sdk/assets/js/nojquery.ba-postmessage.js (added)
-
vendor/freemius/wordpress-sdk/assets/js/postmessage.js (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/14fb1bd5b7c41648488b06147f50a0dc.svg (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/178afa6030e76635dbe835e111d2c507.png (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/27b5a722a5553d9de0170325267fccec.png (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/4375c4a3ddc6f637c2ab9a2d7220f91e.png (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/45da596e2b512ffc3bb638baaf0fdc4e.png (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/a34e046aee1702a5690679750a7f4d0f.svg (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/b09d0b38b627c2fa564d050f79f2f064.svg (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/c03f665db27af43971565560adfba594.png (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/cb5fc4f6ec7ada72e986f6e7dde365bf.png (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/d65812c447b4523b42d59018e1c0bb53.png (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/f3aac72a8e63997d6bb888f816457e9b.png (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/fde48e4609a6ddc11d639fc2421f2afd.png (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/freemius-pricing.js (added)
-
vendor/freemius/wordpress-sdk/assets/js/pricing/freemius-pricing.js.LICENSE.txt (added)
-
vendor/freemius/wordpress-sdk/config.php (added)
-
vendor/freemius/wordpress-sdk/includes (added)
-
vendor/freemius/wordpress-sdk/includes/class-freemius-abstract.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-freemius.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-fs-admin-notices.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-fs-api.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-fs-garbage-collector.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-fs-hook-snapshot.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-fs-lock.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-fs-logger.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-fs-options.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-fs-plugin-updater.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-fs-security.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-fs-storage.php (added)
-
vendor/freemius/wordpress-sdk/includes/class-fs-user-lock.php (added)
-
vendor/freemius/wordpress-sdk/includes/customizer (added)
-
vendor/freemius/wordpress-sdk/includes/customizer/class-fs-customizer-support-section.php (added)
-
vendor/freemius/wordpress-sdk/includes/customizer/class-fs-customizer-upsell-control.php (added)
-
vendor/freemius/wordpress-sdk/includes/customizer/index.php (added)
-
vendor/freemius/wordpress-sdk/includes/debug (added)
-
vendor/freemius/wordpress-sdk/includes/debug/class-fs-debug-bar-panel.php (added)
-
vendor/freemius/wordpress-sdk/includes/debug/debug-bar-start.php (added)
-
vendor/freemius/wordpress-sdk/includes/debug/index.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-affiliate-terms.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-affiliate.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-billing.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-entity.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-payment.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-plugin-info.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-plugin-license.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-plugin-plan.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-plugin-tag.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-plugin.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-pricing.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-scope-entity.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-site.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-subscription.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/class-fs-user.php (added)
-
vendor/freemius/wordpress-sdk/includes/entities/index.php (added)
-
vendor/freemius/wordpress-sdk/includes/fs-core-functions.php (added)
-
vendor/freemius/wordpress-sdk/includes/fs-essential-functions.php (added)
-
vendor/freemius/wordpress-sdk/includes/fs-html-escaping-functions.php (added)
-
vendor/freemius/wordpress-sdk/includes/fs-plugin-info-dialog.php (added)
-
vendor/freemius/wordpress-sdk/includes/index.php (added)
-
vendor/freemius/wordpress-sdk/includes/l10n.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-admin-menu-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-admin-notice-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-cache-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-checkout-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-clone-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-contact-form-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-debug-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-gdpr-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-key-value-storage.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-license-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-option-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-permission-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-plan-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/class-fs-plugin-manager.php (added)
-
vendor/freemius/wordpress-sdk/includes/managers/index.php (added)
-
vendor/freemius/wordpress-sdk/includes/sdk (added)
-
vendor/freemius/wordpress-sdk/includes/sdk/Exceptions (added)
-
vendor/freemius/wordpress-sdk/includes/sdk/Exceptions/ArgumentNotExistException.php (added)
-
vendor/freemius/wordpress-sdk/includes/sdk/Exceptions/EmptyArgumentException.php (added)
-
vendor/freemius/wordpress-sdk/includes/sdk/Exceptions/Exception.php (added)
-
vendor/freemius/wordpress-sdk/includes/sdk/Exceptions/InvalidArgumentException.php (added)
-
vendor/freemius/wordpress-sdk/includes/sdk/Exceptions/OAuthException.php (added)
-
vendor/freemius/wordpress-sdk/includes/sdk/Exceptions/index.php (added)
-
vendor/freemius/wordpress-sdk/includes/sdk/FreemiusBase.php (added)
-
vendor/freemius/wordpress-sdk/includes/sdk/FreemiusWordPress.php (added)
-
vendor/freemius/wordpress-sdk/includes/sdk/index.php (added)
-
vendor/freemius/wordpress-sdk/includes/supplements (added)
-
vendor/freemius/wordpress-sdk/includes/supplements/fs-essential-functions-1.1.7.1.php (added)
-
vendor/freemius/wordpress-sdk/includes/supplements/fs-essential-functions-2.2.1.php (added)
-
vendor/freemius/wordpress-sdk/includes/supplements/fs-migration-2.5.1.php (added)
-
vendor/freemius/wordpress-sdk/includes/supplements/index.php (added)
-
vendor/freemius/wordpress-sdk/index.php (added)
-
vendor/freemius/wordpress-sdk/languages (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-cs_CZ.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-da_DK.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-de_DE.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-es_ES.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-fr_FR.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-he_IL.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-hu_HU.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-it_IT.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-ja.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-nl_NL.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-ru_RU.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-ta.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius-zh_CN.mo (added)
-
vendor/freemius/wordpress-sdk/languages/freemius.pot (added)
-
vendor/freemius/wordpress-sdk/languages/index.php (added)
-
vendor/freemius/wordpress-sdk/require.php (added)
-
vendor/freemius/wordpress-sdk/start.php (added)
-
vendor/freemius/wordpress-sdk/templates (added)
-
vendor/freemius/wordpress-sdk/templates/account (added)
-
vendor/freemius/wordpress-sdk/templates/account.php (added)
-
vendor/freemius/wordpress-sdk/templates/account/billing.php (added)
-
vendor/freemius/wordpress-sdk/templates/account/index.php (added)
-
vendor/freemius/wordpress-sdk/templates/account/partials (added)
-
vendor/freemius/wordpress-sdk/templates/account/partials/activate-license-button.php (added)
-
vendor/freemius/wordpress-sdk/templates/account/partials/addon.php (added)
-
vendor/freemius/wordpress-sdk/templates/account/partials/deactivate-license-button.php (added)
-
vendor/freemius/wordpress-sdk/templates/account/partials/disconnect-button.php (added)
-
vendor/freemius/wordpress-sdk/templates/account/partials/index.php (added)
-
vendor/freemius/wordpress-sdk/templates/account/partials/site.php (added)
-
vendor/freemius/wordpress-sdk/templates/account/payments.php (added)
-
vendor/freemius/wordpress-sdk/templates/add-ons.php (added)
-
vendor/freemius/wordpress-sdk/templates/add-trial-to-pricing.php (added)
-
vendor/freemius/wordpress-sdk/templates/admin-notice.php (added)
-
vendor/freemius/wordpress-sdk/templates/ajax-loader.php (added)
-
vendor/freemius/wordpress-sdk/templates/api-connectivity-message-js.php (added)
-
vendor/freemius/wordpress-sdk/templates/auto-installation.php (added)
-
vendor/freemius/wordpress-sdk/templates/checkout (added)
-
vendor/freemius/wordpress-sdk/templates/checkout.php (added)
-
vendor/freemius/wordpress-sdk/templates/checkout/frame.php (added)
-
vendor/freemius/wordpress-sdk/templates/checkout/process-redirect.php (added)
-
vendor/freemius/wordpress-sdk/templates/checkout/redirect.php (added)
-
vendor/freemius/wordpress-sdk/templates/clone-resolution-js.php (added)
-
vendor/freemius/wordpress-sdk/templates/connect (added)
-
vendor/freemius/wordpress-sdk/templates/connect.php (added)
-
vendor/freemius/wordpress-sdk/templates/connect/index.php (added)
-
vendor/freemius/wordpress-sdk/templates/connect/permission.php (added)
-
vendor/freemius/wordpress-sdk/templates/connect/permissions-group.php (added)
-
vendor/freemius/wordpress-sdk/templates/contact.php (added)
-
vendor/freemius/wordpress-sdk/templates/debug (added)
-
vendor/freemius/wordpress-sdk/templates/debug.php (added)
-
vendor/freemius/wordpress-sdk/templates/debug/api-calls.php (added)
-
vendor/freemius/wordpress-sdk/templates/debug/index.php (added)
-
vendor/freemius/wordpress-sdk/templates/debug/logger.php (added)
-
vendor/freemius/wordpress-sdk/templates/debug/plugins-themes-sync.php (added)
-
vendor/freemius/wordpress-sdk/templates/debug/scheduled-crons.php (added)
-
vendor/freemius/wordpress-sdk/templates/email.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms (added)
-
vendor/freemius/wordpress-sdk/templates/forms/affiliation.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/data-debug-mode.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/deactivation (added)
-
vendor/freemius/wordpress-sdk/templates/forms/deactivation/contact.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/deactivation/form.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/deactivation/index.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/deactivation/retry-skip.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/email-address-update.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/index.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/license-activation.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/optout.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/premium-versions-upgrade-handler.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/premium-versions-upgrade-metadata.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/resend-key.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/subscription-cancellation.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/trial-start.php (added)
-
vendor/freemius/wordpress-sdk/templates/forms/user-change.php (added)
-
vendor/freemius/wordpress-sdk/templates/gdpr-optin-js.php (added)
-
vendor/freemius/wordpress-sdk/templates/index.php (added)
-
vendor/freemius/wordpress-sdk/templates/js (added)
-
vendor/freemius/wordpress-sdk/templates/js/index.php (added)
-
vendor/freemius/wordpress-sdk/templates/js/jquery.content-change.php (added)
-
vendor/freemius/wordpress-sdk/templates/js/open-license-activation.php (added)
-
vendor/freemius/wordpress-sdk/templates/js/permissions.php (added)
-
vendor/freemius/wordpress-sdk/templates/js/style-premium-theme.php (added)
-
vendor/freemius/wordpress-sdk/templates/partials (added)
-
vendor/freemius/wordpress-sdk/templates/partials/index.php (added)
-
vendor/freemius/wordpress-sdk/templates/partials/network-activation.php (added)
-
vendor/freemius/wordpress-sdk/templates/plugin-icon.php (added)
-
vendor/freemius/wordpress-sdk/templates/plugin-info (added)
-
vendor/freemius/wordpress-sdk/templates/plugin-info/description.php (added)
-
vendor/freemius/wordpress-sdk/templates/plugin-info/features.php (added)
-
vendor/freemius/wordpress-sdk/templates/plugin-info/index.php (added)
-
vendor/freemius/wordpress-sdk/templates/plugin-info/screenshots.php (added)
-
vendor/freemius/wordpress-sdk/templates/pricing.php (added)
-
vendor/freemius/wordpress-sdk/templates/secure-https-header.php (added)
-
vendor/freemius/wordpress-sdk/templates/sticky-admin-notice-js.php (added)
-
vendor/freemius/wordpress-sdk/templates/tabs-capture-js.php (added)
-
vendor/freemius/wordpress-sdk/templates/tabs.php (added)
-
vendor/soundasleep/html2text/.gitignore (modified) (1 diff)
-
vendor/soundasleep/html2text/.travis.yml (deleted)
-
vendor/soundasleep/html2text/README.md (modified) (3 diffs)
-
vendor/soundasleep/html2text/composer.json (modified) (1 diff)
-
vendor/soundasleep/html2text/composer.lock (deleted)
-
vendor/soundasleep/html2text/phpstan.neon.dist (added)
-
vendor/soundasleep/html2text/src/Html2Text.php (modified) (24 diffs)
-
vendor/soundasleep/html2text/src/Html2TextException.php (modified) (1 diff)
-
vendor/soundasleep/html2text/tests (deleted)
Legend:
- Unmodified
- Added
- Removed
-
email-tracker/trunk/assets/build/index.asset.php
r2566316 r3416646 1 <?php return array('dependencies' => array('moment', ' wp-api-fetch', 'wp-components', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => 'c0bb78bc83ecd06779758f4f9738862a');1 <?php return array('dependencies' => array('moment', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '9c6b96efc3afffb40ba4'); -
email-tracker/trunk/assets/build/index.js
r2670982 r3416646 1 /******/ (function(modules) { // webpackBootstrap 1 /******/ (() => { // webpackBootstrap 2 /******/ "use strict"; 3 /******/ var __webpack_modules__ = ({ 4 5 /***/ "@wordpress/api-fetch": 6 /*!**********************************!*\ 7 !*** external ["wp","apiFetch"] ***! 8 \**********************************/ 9 /***/ ((module) => { 10 11 module.exports = window["wp"]["apiFetch"]; 12 13 /***/ }), 14 15 /***/ "@wordpress/components": 16 /*!************************************!*\ 17 !*** external ["wp","components"] ***! 18 \************************************/ 19 /***/ ((module) => { 20 21 module.exports = window["wp"]["components"]; 22 23 /***/ }), 24 25 /***/ "@wordpress/element": 26 /*!*********************************!*\ 27 !*** external ["wp","element"] ***! 28 \*********************************/ 29 /***/ ((module) => { 30 31 module.exports = window["wp"]["element"]; 32 33 /***/ }), 34 35 /***/ "@wordpress/i18n": 36 /*!******************************!*\ 37 !*** external ["wp","i18n"] ***! 38 \******************************/ 39 /***/ ((module) => { 40 41 module.exports = window["wp"]["i18n"]; 42 43 /***/ }), 44 45 /***/ "moment": 46 /*!*************************!*\ 47 !*** external "moment" ***! 48 \*************************/ 49 /***/ ((module) => { 50 51 module.exports = window["moment"]; 52 53 /***/ }), 54 55 /***/ "react/jsx-runtime": 56 /*!**********************************!*\ 57 !*** external "ReactJSXRuntime" ***! 58 \**********************************/ 59 /***/ ((module) => { 60 61 module.exports = window["ReactJSXRuntime"]; 62 63 /***/ }) 64 65 /******/ }); 66 /************************************************************************/ 2 67 /******/ // The module cache 3 /******/ var installedModules= {};4 /******/ 68 /******/ var __webpack_module_cache__ = {}; 69 /******/ 5 70 /******/ // The require function 6 71 /******/ function __webpack_require__(moduleId) { 7 /******/8 72 /******/ // Check if module is in cache 9 /******/ if(installedModules[moduleId]) { 10 /******/ return installedModules[moduleId].exports; 73 /******/ var cachedModule = __webpack_module_cache__[moduleId]; 74 /******/ if (cachedModule !== undefined) { 75 /******/ return cachedModule.exports; 11 76 /******/ } 12 77 /******/ // Create a new module (and put it into the cache) 13 /******/ var module = installedModules[moduleId] = {14 /******/ i: moduleId,15 /******/ l: false,78 /******/ var module = __webpack_module_cache__[moduleId] = { 79 /******/ // no module.id needed 80 /******/ // no module.loaded needed 16 81 /******/ exports: {} 17 82 /******/ }; 18 /******/ 83 /******/ 19 84 /******/ // Execute the module function 20 /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 /******/ 22 /******/ // Flag the module as loaded 23 /******/ module.l = true; 24 /******/ 85 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 86 /******/ 25 87 /******/ // Return the exports of the module 26 88 /******/ return module.exports; 27 89 /******/ } 28 /******/ 29 /******/ 30 /******/ // expose the modules object (__webpack_modules__) 31 /******/ __webpack_require__.m = modules; 32 /******/ 33 /******/ // expose the module cache 34 /******/ __webpack_require__.c = installedModules; 35 /******/ 36 /******/ // define getter function for harmony exports 37 /******/ __webpack_require__.d = function(exports, name, getter) { 38 /******/ if(!__webpack_require__.o(exports, name)) { 39 /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 40 /******/ } 41 /******/ }; 42 /******/ 43 /******/ // define __esModule on exports 44 /******/ __webpack_require__.r = function(exports) { 45 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 46 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 47 /******/ } 48 /******/ Object.defineProperty(exports, '__esModule', { value: true }); 49 /******/ }; 50 /******/ 51 /******/ // create a fake namespace object 52 /******/ // mode & 1: value is a module id, require it 53 /******/ // mode & 2: merge all properties of value into the ns 54 /******/ // mode & 4: return value when already ns object 55 /******/ // mode & 8|1: behave like require 56 /******/ __webpack_require__.t = function(value, mode) { 57 /******/ if(mode & 1) value = __webpack_require__(value); 58 /******/ if(mode & 8) return value; 59 /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 60 /******/ var ns = Object.create(null); 61 /******/ __webpack_require__.r(ns); 62 /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 63 /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 64 /******/ return ns; 65 /******/ }; 66 /******/ 67 /******/ // getDefaultExport function for compatibility with non-harmony modules 68 /******/ __webpack_require__.n = function(module) { 69 /******/ var getter = module && module.__esModule ? 70 /******/ function getDefault() { return module['default']; } : 71 /******/ function getModuleExports() { return module; }; 72 /******/ __webpack_require__.d(getter, 'a', getter); 73 /******/ return getter; 74 /******/ }; 75 /******/ 76 /******/ // Object.prototype.hasOwnProperty.call 77 /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 78 /******/ 79 /******/ // __webpack_public_path__ 80 /******/ __webpack_require__.p = ""; 81 /******/ 82 /******/ 83 /******/ // Load entry module and return exports 84 /******/ return __webpack_require__(__webpack_require__.s = "./src/index.js"); 85 /******/ }) 90 /******/ 86 91 /************************************************************************/ 87 /******/ ({ 88 89 /***/ "./node_modules/@babel/runtime/helpers/defineProperty.js": 90 /*!***************************************************************!*\ 91 !*** ./node_modules/@babel/runtime/helpers/defineProperty.js ***! 92 \***************************************************************/ 93 /*! no static exports found */ 94 /***/ (function(module, exports) { 95 96 function _defineProperty(obj, key, value) { 97 if (key in obj) { 98 Object.defineProperty(obj, key, { 99 value: value, 100 enumerable: true, 101 configurable: true, 102 writable: true 103 }); 104 } else { 105 obj[key] = value; 106 } 107 108 return obj; 109 } 110 111 module.exports = _defineProperty; 112 module.exports["default"] = module.exports, module.exports.__esModule = true; 113 114 /***/ }), 115 116 /***/ "./node_modules/@babel/runtime/helpers/extends.js": 117 /*!********************************************************!*\ 118 !*** ./node_modules/@babel/runtime/helpers/extends.js ***! 119 \********************************************************/ 120 /*! no static exports found */ 121 /***/ (function(module, exports) { 122 123 function _extends() { 124 module.exports = _extends = Object.assign || function (target) { 125 for (var i = 1; i < arguments.length; i++) { 126 var source = arguments[i]; 127 128 for (var key in source) { 129 if (Object.prototype.hasOwnProperty.call(source, key)) { 130 target[key] = source[key]; 131 } 132 } 133 } 134 135 return target; 136 }; 137 138 module.exports["default"] = module.exports, module.exports.__esModule = true; 139 return _extends.apply(this, arguments); 140 } 141 142 module.exports = _extends; 143 module.exports["default"] = module.exports, module.exports.__esModule = true; 144 145 /***/ }), 146 147 /***/ "./src/index.js": 92 /******/ /* webpack/runtime/compat get default export */ 93 /******/ (() => { 94 /******/ // getDefaultExport function for compatibility with non-harmony modules 95 /******/ __webpack_require__.n = (module) => { 96 /******/ var getter = module && module.__esModule ? 97 /******/ () => (module['default']) : 98 /******/ () => (module); 99 /******/ __webpack_require__.d(getter, { a: getter }); 100 /******/ return getter; 101 /******/ }; 102 /******/ })(); 103 /******/ 104 /******/ /* webpack/runtime/define property getters */ 105 /******/ (() => { 106 /******/ // define getter functions for harmony exports 107 /******/ __webpack_require__.d = (exports, definition) => { 108 /******/ for(var key in definition) { 109 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 110 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 111 /******/ } 112 /******/ } 113 /******/ }; 114 /******/ })(); 115 /******/ 116 /******/ /* webpack/runtime/hasOwnProperty shorthand */ 117 /******/ (() => { 118 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 119 /******/ })(); 120 /******/ 121 /******/ /* webpack/runtime/make namespace object */ 122 /******/ (() => { 123 /******/ // define __esModule on exports 124 /******/ __webpack_require__.r = (exports) => { 125 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 126 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 127 /******/ } 128 /******/ Object.defineProperty(exports, '__esModule', { value: true }); 129 /******/ }; 130 /******/ })(); 131 /******/ 132 /************************************************************************/ 133 var __webpack_exports__ = {}; 134 // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk. 135 (() => { 148 136 /*!**********************!*\ 149 137 !*** ./src/index.js ***! 150 138 \**********************/ 151 /*! no exports provided */152 /***/ (function(module, __webpack_exports__, __webpack_require__) {153 154 "use strict";155 139 __webpack_require__.r(__webpack_exports__); 156 /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/extends */ "./node_modules/@babel/runtime/helpers/extends.js"); 157 /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__); 158 /* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/defineProperty */ "./node_modules/@babel/runtime/helpers/defineProperty.js"); 159 /* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1__); 160 /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element"); 161 /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__); 162 /* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components"); 163 /* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__); 164 /* harmony import */ var _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @wordpress/api-fetch */ "@wordpress/api-fetch"); 165 /* harmony import */ var _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_4__); 166 /* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n"); 167 /* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__); 168 /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! moment */ "moment"); 169 /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_6__); 170 171 172 140 /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element"); 141 /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__); 142 /* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components"); 143 /* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__); 144 /* harmony import */ var _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/api-fetch */ "@wordpress/api-fetch"); 145 /* harmony import */ var _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2__); 146 /* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n"); 147 /* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_3__); 148 /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! moment */ "moment"); 149 /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_4__); 150 /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime"); 151 /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__); 173 152 174 153 … … 180 159 181 160 182 class EmailModalView extends _wordpress_element__WEBPACK_IMPORTED_MODULE_ 2__["Component"]{161 class EmailModalView extends _wordpress_element__WEBPACK_IMPORTED_MODULE_0__.Component { 183 162 constructor(props) { 184 163 super(props); 185 186 _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1___default()(this, "setOpen", openFlag => {187 this.setState({188 isOpen: openFlag189 });190 });191 192 _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1___default()(this, "closeModal", () => {193 this.setOpen(false);194 });195 196 164 this.state = { 197 165 isOpen: true, … … 210 178 }; 211 179 } 212 213 180 componentDidMount() { 214 _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_ 4___default()({181 _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2___default()({ 215 182 path: '/email-tracker/v1/email/' + this.props.id + '/', 216 183 method: 'GET' 217 184 }).then(res => { 218 this.setState({ ...res, 185 this.setState({ 186 ...res, 219 187 isLoading: false 220 188 }); … … 226 194 }); 227 195 } 228 196 setOpen = openFlag => { 197 this.setState({ 198 isOpen: openFlag 199 }); 200 }; 201 closeModal = () => { 202 this.setOpen(false); 203 }; 229 204 render() { 230 205 const { … … 233 208 subject 234 209 } = this.props; 235 const title = sprintf(Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__["__"])(' Sub.: %s', 'email-tracker'), subject);210 const title = (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_3__.sprintf)((0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_3__.__)(' Sub.: %s', 'email-tracker'), subject); 236 211 const icon = 'email-alt'; 237 212 const isDismissible = true; … … 239 214 const shouldCloseOnEsc = true; 240 215 const shouldCloseOnClickOutside = true; 241 const iconComponent = icon ? Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["Dashicon"], {216 const iconComponent = icon ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Dashicon, { 242 217 icon: icon 243 218 }) : null; … … 251 226 }; 252 227 let modalBody; 253 254 228 if (this.state.isLoading) { 255 modalBody = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["Spinner"], {229 modalBody = /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Spinner, { 256 230 color: "blue", 257 231 size: "200" 258 232 }); 259 233 } else { 260 const moment_local_email = moment__WEBPACK_IMPORTED_MODULE_ 6___default.a.utc(this.state.date_time).local();234 const moment_local_email = moment__WEBPACK_IMPORTED_MODULE_4___default().utc(this.state.date_time).local(); 261 235 let read_log_panel_body; 262 263 236 if (this.state.read_log.length) { 264 read_log_panel_body = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])("ol", null, this.state.read_log.map(read_log => { 265 let read_local_moment = moment__WEBPACK_IMPORTED_MODULE_6___default.a.utc(read_log.date_time).local(); 266 return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])("li", null, sprintf(Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__["__"])('Read at %s on IP %s', 'email-tracker'), read_local_moment.format('MMMM Do YYYY, dddd, h:mm:ss a') + ' (' + read_local_moment.fromNow() + ')', read_log.ip_address)); 267 }))); 237 read_log_panel_body = /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelRow, { 238 children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("ol", { 239 children: this.state.read_log.map((read_log, index) => { 240 let read_local_moment = moment__WEBPACK_IMPORTED_MODULE_4___default().utc(read_log.date_time).local(); 241 return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("li", { 242 children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_3__.sprintf)((0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_3__.__)('Read at %s on IP %s', 'email-tracker'), read_local_moment.format('MMMM Do YYYY, dddd, h:mm:ss a') + ' (' + read_local_moment.fromNow() + ')', read_log.ip_address) 243 }, index); 244 }) 245 }) 246 }); 268 247 } else { 269 read_log_panel_body = Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__["__"])('N/A', 'email-tracker');248 read_log_panel_body = (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_3__.__)('N/A', 'email-tracker'); 270 249 } 271 272 250 let state = this.state; 273 251 let extra_panel = applyFilters('email-tracker-view-email-extra-panel', null, state); 274 modalBody = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["Fragment"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["Panel"], { 275 header: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__["__"])('Email Receiver Activity Log', 'email-tracker') 276 }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelBody"], { 277 title: "#" + sprintf(Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__["_n"])('%d time read', '%d times read', parseInt(this.state.total_read_count), 'email-tracker'), this.state.total_read_count), 278 initialOpen: this.state.read_log.length ? true : false 279 }, read_log_panel_body), extra_panel), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])("br", null), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["Panel"], { 280 header: "Email Data" 281 }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelBody"], { 282 title: "To", 283 initialOpen: true 284 }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelRow"], null, this.state.to)), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelBody"], { 285 title: "Send Date Time", 286 initialOpen: true 287 }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelRow"], null, moment_local_email.format('MMMM Do YYYY, dddd, h:mm:ss a'), " (", moment_local_email.fromNow(), ")")), this.state.headers && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelBody"], { 288 title: "Headers", 289 initialOpen: true 290 }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelRow"], null, this.state.headers)), this.state.attachments && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelBody"], { 291 title: "Attachments", 292 initialOpen: true 293 }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelRow"], null, this.state.attachments.split(",\\n").map(attachment => { 294 let attachment_url = email_tracker.content_url + attachment; 295 let attachment_split = attachment.split("/"); 296 return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["Fragment"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])("a", { 297 href: attachment_url, 298 target: "_blank" 299 }, attachment_split[attachment_split.length - 1])); 300 }))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelBody"], { 301 title: "Message", 302 initialOpen: true 303 }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelRow"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])("div", { 304 dangerouslySetInnerHTML: { 305 __html: this.state.message 306 } 307 })))), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])("br", null), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["Button"], { 308 isDestructive: true, 309 isSmall: true, 310 onClick: this.closeModal 311 }, Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__["__"])('Close', 'email-tracker'))); 252 modalBody = /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 253 children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Panel, { 254 header: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_3__.__)('Email Receiver Activity Log', 'email-tracker'), 255 children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelBody, { 256 title: "#" + (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_3__.sprintf)((0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_3__._n)('%d time read', '%d times read', parseInt(this.state.total_read_count), 'email-tracker'), this.state.total_read_count), 257 initialOpen: this.state.read_log.length ? true : false, 258 children: read_log_panel_body 259 }), extra_panel] 260 }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("br", {}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Panel, { 261 header: "Email Data", 262 children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelBody, { 263 title: "To", 264 initialOpen: true, 265 children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelRow, { 266 children: this.state.to 267 }) 268 }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelBody, { 269 title: "Send Date Time", 270 initialOpen: true, 271 children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelRow, { 272 children: [moment_local_email.format('MMMM Do YYYY, dddd, h:mm:ss a'), " (", moment_local_email.fromNow(), ")"] 273 }) 274 }), this.state.headers && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelBody, { 275 title: "Headers", 276 initialOpen: true, 277 children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelRow, { 278 children: this.state.headers 279 }) 280 }), this.state.attachments && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelBody, { 281 title: "Attachments", 282 initialOpen: true, 283 children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelRow, { 284 children: this.state.attachments.split(",\\n").map((attachment, index) => { 285 let attachment_url = email_tracker.content_url + attachment; 286 let attachment_split = attachment.split("/"); 287 return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 288 children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("a", { 289 href: attachment_url, 290 target: "_blank", 291 children: attachment_split[attachment_split.length - 1] 292 }) 293 }, index); 294 }) 295 }) 296 }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelBody, { 297 title: "Message", 298 initialOpen: true, 299 children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelRow, { 300 children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", { 301 dangerouslySetInnerHTML: { 302 __html: this.state.message 303 } 304 }) 305 }) 306 })] 307 }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("br", {}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Button, { 308 isDestructive: true, 309 isSmall: true, 310 onClick: this.closeModal, 311 children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_3__.__)('Close', 'email-tracker') 312 })] 313 }); 312 314 } 313 314 return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["Fragment"], null, this.state.isOpen && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["Modal"], _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default()({}, modalProps, { 315 style: { 316 minWidth: '75%' 317 }, 318 onRequestClose: this.closeModal 319 }), modalBody)); 315 return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 316 children: this.state.isOpen && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Modal, { 317 ...modalProps, 318 style: { 319 minWidth: '75%' 320 }, 321 onRequestClose: this.closeModal, 322 children: modalBody 323 }) 324 }); 320 325 } 321 322 326 } 323 324 327 window.EMTRLoadView = function EMTRLoadView(id, subject = '', to = '') { 325 328 let passProps = { … … 328 331 to 329 332 }; 330 const root = document.getElementById('emtr-email-view-modal-container'); 331 Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["unmountComponentAtNode"])(root); 332 Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["render"])(Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__["createElement"])(EmailModalView, passProps), root); 333 const container = document.getElementById('emtr-email-view-modal-container'); 334 const root = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createRoot)(container); 335 336 // root.unmount(); // Unmount the component from the root 337 338 root.render(/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(EmailModalView, { 339 ...passProps 340 })); 333 341 return false; 334 342 }; 335 336 /***/ }), 337 338 /***/ "@wordpress/api-fetch": 339 /*!**********************************!*\ 340 !*** external ["wp","apiFetch"] ***! 341 \**********************************/ 342 /*! no static exports found */ 343 /***/ (function(module, exports) { 344 345 (function() { module.exports = window["wp"]["apiFetch"]; }()); 346 347 /***/ }), 348 349 /***/ "@wordpress/components": 350 /*!************************************!*\ 351 !*** external ["wp","components"] ***! 352 \************************************/ 353 /*! no static exports found */ 354 /***/ (function(module, exports) { 355 356 (function() { module.exports = window["wp"]["components"]; }()); 357 358 /***/ }), 359 360 /***/ "@wordpress/element": 361 /*!*********************************!*\ 362 !*** external ["wp","element"] ***! 363 \*********************************/ 364 /*! no static exports found */ 365 /***/ (function(module, exports) { 366 367 (function() { module.exports = window["wp"]["element"]; }()); 368 369 /***/ }), 370 371 /***/ "@wordpress/i18n": 372 /*!******************************!*\ 373 !*** external ["wp","i18n"] ***! 374 \******************************/ 375 /*! no static exports found */ 376 /***/ (function(module, exports) { 377 378 (function() { module.exports = window["wp"]["i18n"]; }()); 379 380 /***/ }), 381 382 /***/ "moment": 383 /*!*************************!*\ 384 !*** external "moment" ***! 385 \*************************/ 386 /*! no static exports found */ 387 /***/ (function(module, exports) { 388 389 (function() { module.exports = window["moment"]; }()); 390 391 /***/ }) 392 393 /******/ }); 343 })(); 344 345 /******/ })() 346 ; 394 347 //# sourceMappingURL=index.js.map -
email-tracker/trunk/assets/build/index.js.map
r2566316 r3416646 1 {"version":3," sources":["webpack:///webpack/bootstrap","webpack:///./node_modules/@babel/runtime/helpers/defineProperty.js","webpack:///./node_modules/@babel/runtime/helpers/extends.js","webpack:///./src/index.js","webpack:///external [\"wp\",\"apiFetch\"]","webpack:///external [\"wp\",\"components\"]","webpack:///external [\"wp\",\"element\"]","webpack:///external [\"wp\",\"i18n\"]","webpack:///external \"moment\""],"names":["applyFilters","wp","hooks","EmailModalView","Component","constructor","props","openFlag","setState","isOpen","setOpen","state","isLoading","total_read_count","total_link_click_count","to","subject","message","message_plain","headers","attachments","date_time","read_log","link_click_log","componentDidMount","apiFetch","path","id","method","then","res","error","alert","code","render","title","sprintf","__","icon","isDismissible","focusOnMount","shouldCloseOnEsc","shouldCloseOnClickOutside","iconComponent","modalProps","modalBody","moment_local_email","moment","utc","local","read_log_panel_body","length","map","read_local_moment","format","fromNow","ip_address","extra_panel","_n","parseInt","split","attachment","attachment_url","email_tracker","content_url","attachment_split","__html","closeModal","minWidth","window","EMTRLoadView","passProps","root","document","getElementById","unmountComponentAtNode"],"mappings":"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","file":"index.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/index.js\");\n","function _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}\n\nmodule.exports = _defineProperty;\nmodule.exports[\"default\"] = module.exports, module.exports.__esModule = true;","function _extends() {\n module.exports = _extends = Object.assign || function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n };\n\n module.exports[\"default\"] = module.exports, module.exports.__esModule = true;\n return _extends.apply(this, arguments);\n}\n\nmodule.exports = _extends;\nmodule.exports[\"default\"] = module.exports, module.exports.__esModule = true;","\nimport { render, unmountComponentAtNode, Fragment, Component } from '@wordpress/element';\nimport { ButtonGroup, Button, Dashicon, Modal, Panel, PanelRow, PanelBody, Spinner } from '@wordpress/components';\n\nconst { applyFilters } = wp.hooks;\nimport apiFetch from '@wordpress/api-fetch';\nimport { __, _n } from '@wordpress/i18n';\n\nimport moment from 'moment';\n\nclass EmailModalView extends Component {\n\n constructor( props ) {\n super( props );\n this.state = {\n isOpen: true,\n isLoading: true,\n total_read_count: 0,\n total_link_click_count: 0,\n to: '',\n subject: '',\n message: '',\n message_plain: '',\n headers: '',\n attachments: '',\n date_time: '',\n read_log: [],\n link_click_log: [],\n };\n }\n\n componentDidMount() {\n apiFetch( {\n path: '/email-tracker/v1/email/' + this.props.id + '/',\n method: 'GET',\n } ).then( ( res ) => {\n this.setState({\n ...res,\n isLoading: false,\n });\n \n \n }, (error) => {\n this.setState( {\n isLoading: false,\n } );\n alert( 'Error in fetching an email with the message: ' + error.message + '(' + error.code +')' )\n } );\n }\n\n setOpen = ( openFlag ) => {\n this.setState({\n isOpen: openFlag\n });\n }\n\n closeModal = () => {\n this.setOpen( false );\n }\n\n render() {\n const { id, to, subject } = this.props;\n\n const title = sprintf( __(' Sub.: %s', 'email-tracker'), subject );\n const icon = 'email-alt';\n const isDismissible = true;\n const focusOnMount = true;\n const shouldCloseOnEsc = true;\n const shouldCloseOnClickOutside = true;\n\n const iconComponent = icon ? <Dashicon icon={ icon } /> : null;\n\n const modalProps = {\n icon: iconComponent,\n focusOnMount,\n isDismissible,\n shouldCloseOnEsc,\n shouldCloseOnClickOutside,\n title,\n };\n\n let modalBody;\n if ( this.state.isLoading ) {\n modalBody = (\n <Spinner color=\"blue\" size=\"200\" />\n );\n } else {\n const moment_local_email = moment.utc( this.state.date_time ).local();\n\n let read_log_panel_body;\n if ( this.state.read_log.length ) {\n read_log_panel_body = (\n <PanelRow>\n <ol>\n { this.state.read_log.map( read_log => {\n let read_local_moment = moment.utc( read_log.date_time ).local();\n return (\n <li>\n { sprintf( __( 'Read at %s on IP %s', 'email-tracker'), read_local_moment.format( 'MMMM Do YYYY, dddd, h:mm:ss a' ) + ' (' + read_local_moment.fromNow() + ')', read_log.ip_address )}\n </li>\n )\n }\n )}\n </ol>\n </PanelRow> );\n } else {\n read_log_panel_body = __( 'N/A', 'email-tracker' );\n }\n \n let state = this.state;\n let extra_panel = applyFilters( 'email-tracker-view-email-extra-panel', null, state );\n \n modalBody = (\n <Fragment>\n <Panel header={ __( 'Email Receiver Activity Log', 'email-tracker') }>\n <PanelBody title={ \"#\" + sprintf( _n( '%d time read', '%d times read', parseInt( this.state.total_read_count ), 'email-tracker' ), this.state.total_read_count ) } initialOpen={ this.state.read_log.length ? true : false } >\n { read_log_panel_body }\n </PanelBody>\n { extra_panel }\n </Panel>\n <br />\n <Panel header=\"Email Data\">\n <PanelBody title={ \"To\" } initialOpen={ true }>\n <PanelRow>{ this.state.to }</PanelRow>\n </PanelBody>\n <PanelBody title={ \"Send Date Time\" } initialOpen={ true }>\n <PanelRow>{ moment_local_email.format( 'MMMM Do YYYY, dddd, h:mm:ss a' ) } ({ moment_local_email.fromNow() })</PanelRow>\n </PanelBody>\n { this.state.headers && \n <PanelBody title={ \"Headers\" } initialOpen={ true }>\n <PanelRow>{ ( this.state.headers ) }</PanelRow>\n </PanelBody>\n }\n { this.state.attachments && \n <PanelBody title={ \"Attachments\" } initialOpen={ true }>\n <PanelRow>\n { this.state.attachments.split(\",\\\\n\").map( attachment => {\n let attachment_url = email_tracker.content_url + attachment;\n let attachment_split = attachment.split(\"/\");\n return (\n <Fragment>\n <a href={attachment_url} target=\"_blank\">{attachment_split[attachment_split.length - 1]}</a>\n </Fragment>\n );\n })}\n </PanelRow>\n </PanelBody>\n }\n <PanelBody title={ \"Message\" } initialOpen={ true }>\n <PanelRow>\n <div dangerouslySetInnerHTML={{__html: this.state.message}}></div>\n </PanelRow>\n </PanelBody>\n </Panel>\n <br />\n <Button isDestructive isSmall={ true } onClick={ this.closeModal } >\n { __('Close', 'email-tracker' ) }\n </Button>\n </Fragment>\n );\n }\n\n return (\n <Fragment>\n \n { this.state.isOpen && \n <Modal { ...modalProps } style={{ minWidth: '75%' }} onRequestClose={ this.closeModal }>\n { modalBody }\n </Modal>\n }\n </Fragment>\n );\n }\n}\n\n\nwindow.EMTRLoadView = function EMTRLoadView( id, subject = '' , to = '' ) {\n let passProps = {\n id,\n subject,\n to,\n };\n\n const root = document.getElementById( 'emtr-email-view-modal-container' );\n\n unmountComponentAtNode( root );\n render( <EmailModalView {...passProps} />, root );\n\n return false;\n}\n\n","(function() { module.exports = window[\"wp\"][\"apiFetch\"]; }());","(function() { module.exports = window[\"wp\"][\"components\"]; }());","(function() { module.exports = window[\"wp\"][\"element\"]; }());","(function() { module.exports = window[\"wp\"][\"i18n\"]; }());","(function() { module.exports = window[\"moment\"]; }());"],"sourceRoot":""}1 {"version":3,"file":"index.js","mappings":"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","sources":["webpack://email-tracker/external window [\"wp\",\"apiFetch\"]","webpack://email-tracker/external window [\"wp\",\"components\"]","webpack://email-tracker/external window [\"wp\",\"element\"]","webpack://email-tracker/external window [\"wp\",\"i18n\"]","webpack://email-tracker/external window \"moment\"","webpack://email-tracker/external window \"ReactJSXRuntime\"","webpack://email-tracker/webpack/bootstrap","webpack://email-tracker/webpack/runtime/compat get default export","webpack://email-tracker/webpack/runtime/define property getters","webpack://email-tracker/webpack/runtime/hasOwnProperty shorthand","webpack://email-tracker/webpack/runtime/make namespace object","webpack://email-tracker/./src/index.js"],"sourcesContent":["module.exports = window[\"wp\"][\"apiFetch\"];","module.exports = window[\"wp\"][\"components\"];","module.exports = window[\"wp\"][\"element\"];","module.exports = window[\"wp\"][\"i18n\"];","module.exports = window[\"moment\"];","module.exports = window[\"ReactJSXRuntime\"];","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","\r\nimport { createRoot, unmountComponentAtNode, Fragment, Component } from '@wordpress/element';\r\nimport { ButtonGroup, Button, Dashicon, Modal, Panel, PanelRow, PanelBody, Spinner } from '@wordpress/components';\r\n\r\nconst { applyFilters } = wp.hooks;\r\nimport apiFetch from '@wordpress/api-fetch';\r\nimport { __, _n, sprintf } from '@wordpress/i18n';\r\n\r\nimport moment from 'moment';\r\n\r\nclass EmailModalView extends Component {\r\n\r\n constructor( props ) {\r\n super( props );\r\n this.state = {\r\n isOpen: true,\r\n isLoading: true,\r\n total_read_count: 0,\r\n total_link_click_count: 0,\r\n to: '',\r\n subject: '',\r\n message: '',\r\n message_plain: '',\r\n headers: '',\r\n attachments: '',\r\n date_time: '',\r\n read_log: [],\r\n link_click_log: [],\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n apiFetch( {\r\n path: '/email-tracker/v1/email/' + this.props.id + '/',\r\n method: 'GET',\r\n } ).then( ( res ) => {\r\n this.setState({\r\n ...res,\r\n isLoading: false,\r\n });\r\n\r\n\r\n }, (error) => {\r\n this.setState( {\r\n isLoading: false,\r\n } );\r\n alert( 'Error in fetching an email with the message: ' + error.message + '(' + error.code +')' )\r\n } );\r\n }\r\n\r\n setOpen = ( openFlag ) => {\r\n this.setState({\r\n isOpen: openFlag\r\n });\r\n }\r\n\r\n closeModal = () => {\r\n this.setOpen( false );\r\n }\r\n\r\n render() {\r\n const { id, to, subject } = this.props;\r\n\r\n const title = sprintf( __(' Sub.: %s', 'email-tracker'), subject );\r\n const icon = 'email-alt';\r\n const isDismissible = true;\r\n const focusOnMount = true;\r\n const shouldCloseOnEsc = true;\r\n const shouldCloseOnClickOutside = true;\r\n\r\n const iconComponent = icon ? <Dashicon icon={ icon } /> : null;\r\n\r\n const modalProps = {\r\n icon: iconComponent,\r\n focusOnMount,\r\n isDismissible,\r\n shouldCloseOnEsc,\r\n shouldCloseOnClickOutside,\r\n title,\r\n };\r\n\r\n let modalBody;\r\n if ( this.state.isLoading ) {\r\n modalBody = (\r\n <Spinner color=\"blue\" size=\"200\" />\r\n );\r\n } else {\r\n const moment_local_email = moment.utc( this.state.date_time ).local();\r\n\r\n let read_log_panel_body;\r\n if ( this.state.read_log.length ) {\r\n read_log_panel_body = (\r\n <PanelRow>\r\n <ol>\r\n\r\n { this.state.read_log.map( (read_log, index) => {\r\n let read_local_moment = moment.utc( read_log.date_time ).local();\r\n return (\r\n <li key={index}>\r\n { sprintf( __( 'Read at %s on IP %s', 'email-tracker'), read_local_moment.format( 'MMMM Do YYYY, dddd, h:mm:ss a' ) + ' (' + read_local_moment.fromNow() + ')', read_log.ip_address )}\r\n </li>\r\n )\r\n }\r\n ) }\r\n </ol>\r\n </PanelRow> );\r\n } else {\r\n read_log_panel_body = __( 'N/A', 'email-tracker' );\r\n }\r\n\r\n let state = this.state;\r\n let extra_panel = applyFilters( 'email-tracker-view-email-extra-panel', null, state );\r\n\r\n modalBody = (\r\n <Fragment>\r\n <Panel header={ __( 'Email Receiver Activity Log', 'email-tracker') }>\r\n <PanelBody title={ \"#\" + sprintf( _n( '%d time read', '%d times read', parseInt( this.state.total_read_count ), 'email-tracker' ), this.state.total_read_count ) } initialOpen={ this.state.read_log.length ? true : false } >\r\n { read_log_panel_body }\r\n </PanelBody>\r\n { extra_panel }\r\n </Panel>\r\n <br />\r\n <Panel header=\"Email Data\">\r\n <PanelBody title={ \"To\" } initialOpen={ true }>\r\n <PanelRow>{ this.state.to }</PanelRow>\r\n </PanelBody>\r\n <PanelBody title={ \"Send Date Time\" } initialOpen={ true }>\r\n <PanelRow>{ moment_local_email.format( 'MMMM Do YYYY, dddd, h:mm:ss a' ) } ({ moment_local_email.fromNow() })</PanelRow>\r\n </PanelBody>\r\n { this.state.headers &&\r\n <PanelBody title={ \"Headers\" } initialOpen={ true }>\r\n <PanelRow>{ ( this.state.headers ) }</PanelRow>\r\n </PanelBody>\r\n }\r\n { this.state.attachments &&\r\n <PanelBody title={ \"Attachments\" } initialOpen={ true }>\r\n <PanelRow>\r\n { this.state.attachments.split(\",\\\\n\").map( (attachment, index) => {\r\n let attachment_url = email_tracker.content_url + attachment;\r\n let attachment_split = attachment.split(\"/\");\r\n return (\r\n <Fragment key={index}>\r\n <a href={attachment_url} target=\"_blank\">{attachment_split[attachment_split.length - 1]}</a>\r\n </Fragment>\r\n );\r\n })}\r\n </PanelRow>\r\n </PanelBody>\r\n }\r\n <PanelBody title={ \"Message\" } initialOpen={ true }>\r\n <PanelRow>\r\n <div dangerouslySetInnerHTML={ { __html: this.state.message } }></div>\r\n </PanelRow>\r\n </PanelBody>\r\n </Panel>\r\n <br />\r\n <Button isDestructive isSmall={ true } onClick={ this.closeModal } >\r\n { __('Close', 'email-tracker' ) }\r\n </Button>\r\n </Fragment>\r\n );\r\n }\r\n\r\n return (\r\n <Fragment>\r\n\r\n { this.state.isOpen &&\r\n <Modal { ...modalProps } style={{ minWidth: '75%' }} onRequestClose={ this.closeModal }>\r\n { modalBody }\r\n </Modal>\r\n }\r\n </Fragment>\r\n );\r\n }\r\n}\r\n\r\n\r\nwindow.EMTRLoadView = function EMTRLoadView( id, subject = '' , to = '' ) {\r\n let passProps = {\r\n id,\r\n subject,\r\n to,\r\n };\r\n\r\n const container = document.getElementById( 'emtr-email-view-modal-container' );\r\n const root = createRoot( container );\r\n\r\n // root.unmount(); // Unmount the component from the root\r\n\r\n root.render( <EmailModalView {...passProps} /> );\r\n\r\n return false;\r\n}\r\n\r\n"],"names":["createRoot","unmountComponentAtNode","Fragment","Component","ButtonGroup","Button","Dashicon","Modal","Panel","PanelRow","PanelBody","Spinner","applyFilters","wp","hooks","apiFetch","__","_n","sprintf","moment","jsx","_jsx","jsxs","_jsxs","EmailModalView","constructor","props","state","isOpen","isLoading","total_read_count","total_link_click_count","to","subject","message","message_plain","headers","attachments","date_time","read_log","link_click_log","componentDidMount","path","id","method","then","res","setState","error","alert","code","setOpen","openFlag","closeModal","render","title","icon","isDismissible","focusOnMount","shouldCloseOnEsc","shouldCloseOnClickOutside","iconComponent","modalProps","modalBody","color","size","moment_local_email","utc","local","read_log_panel_body","length","children","map","index","read_local_moment","format","fromNow","ip_address","extra_panel","header","parseInt","initialOpen","split","attachment","attachment_url","email_tracker","content_url","attachment_split","href","target","dangerouslySetInnerHTML","__html","isDestructive","isSmall","onClick","style","minWidth","onRequestClose","window","EMTRLoadView","passProps","container","document","getElementById","root"],"ignoreList":[],"sourceRoot":""} -
email-tracker/trunk/assets/build/pro/index.asset.php
r2566316 r3416646 1 <?php return array('dependencies' => array('moment', ' wp-components', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '6d820357beb68a09b5a1b1fa9426324c');1 <?php return array('dependencies' => array('moment', 'react-jsx-runtime', 'wp-components', 'wp-i18n'), 'version' => 'f39ca6d29fce395c0cfe'); -
email-tracker/trunk/assets/build/pro/index.js
r2566316 r3416646 1 !function(e){var t={};function n(r){if(t[r])return t[r].exports;var l=t[r]={i:r,l:!1,exports:{}};return e[r].call(l.exports,l,l.exports,n),l.l=!0,l.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var l in e)n.d(r,l,function(t){return e[t]}.bind(null,l));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=4)}([function(e,t){e.exports=window.wp.element},function(e,t){e.exports=window.wp.i18n},function(e,t){e.exports=window.wp.components},function(e,t){e.exports=window.moment},function(e,t,n){"use strict";n.r(t);var r=n(0),l=n(1),o=n(2),i=n(3),c=n.n(i);const{addFilter:a}=wp.hooks;a("email-tracker-view-email-extra-panel","email-tracker/add-click-panel",(e,t)=>{let n;return n=t.total_link_click_count>0?Object(r.createElement)(o.PanelRow,null,Object(r.createElement)("ol",null,t.link_click_log.map(e=>{if(e.date_time){let t=c.a.utc(e.date_time).local();return Object(r.createElement)("li",null,sprintf('"%s" clicked at %s on IP %s',e.link,t.format("MMMM Do YYYY, dddd, h:mm:ss a")+" ("+t.fromNow()+")",e.ip_address))}return null}))):Object(l.__)("N/A","email-tracker"),Object(r.createElement)(o.PanelBody,{title:"#"+sprintf(Object(l._n)("%d time clicked","%d times clicked",parseInt(t.total_link_click_count),"email-tracker"),t.total_link_click_count),initialOpen:!!t.link_click_log.length},n)},10,2)}]); 1 /******/ (() => { // webpackBootstrap 2 /******/ "use strict"; 3 /******/ var __webpack_modules__ = ({ 4 5 /***/ "@wordpress/components": 6 /*!************************************!*\ 7 !*** external ["wp","components"] ***! 8 \************************************/ 9 /***/ ((module) => { 10 11 module.exports = window["wp"]["components"]; 12 13 /***/ }), 14 15 /***/ "@wordpress/i18n": 16 /*!******************************!*\ 17 !*** external ["wp","i18n"] ***! 18 \******************************/ 19 /***/ ((module) => { 20 21 module.exports = window["wp"]["i18n"]; 22 23 /***/ }), 24 25 /***/ "moment": 26 /*!*************************!*\ 27 !*** external "moment" ***! 28 \*************************/ 29 /***/ ((module) => { 30 31 module.exports = window["moment"]; 32 33 /***/ }), 34 35 /***/ "react/jsx-runtime": 36 /*!**********************************!*\ 37 !*** external "ReactJSXRuntime" ***! 38 \**********************************/ 39 /***/ ((module) => { 40 41 module.exports = window["ReactJSXRuntime"]; 42 43 /***/ }) 44 45 /******/ }); 46 /************************************************************************/ 47 /******/ // The module cache 48 /******/ var __webpack_module_cache__ = {}; 49 /******/ 50 /******/ // The require function 51 /******/ function __webpack_require__(moduleId) { 52 /******/ // Check if module is in cache 53 /******/ var cachedModule = __webpack_module_cache__[moduleId]; 54 /******/ if (cachedModule !== undefined) { 55 /******/ return cachedModule.exports; 56 /******/ } 57 /******/ // Create a new module (and put it into the cache) 58 /******/ var module = __webpack_module_cache__[moduleId] = { 59 /******/ // no module.id needed 60 /******/ // no module.loaded needed 61 /******/ exports: {} 62 /******/ }; 63 /******/ 64 /******/ // Execute the module function 65 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 66 /******/ 67 /******/ // Return the exports of the module 68 /******/ return module.exports; 69 /******/ } 70 /******/ 71 /************************************************************************/ 72 /******/ /* webpack/runtime/compat get default export */ 73 /******/ (() => { 74 /******/ // getDefaultExport function for compatibility with non-harmony modules 75 /******/ __webpack_require__.n = (module) => { 76 /******/ var getter = module && module.__esModule ? 77 /******/ () => (module['default']) : 78 /******/ () => (module); 79 /******/ __webpack_require__.d(getter, { a: getter }); 80 /******/ return getter; 81 /******/ }; 82 /******/ })(); 83 /******/ 84 /******/ /* webpack/runtime/define property getters */ 85 /******/ (() => { 86 /******/ // define getter functions for harmony exports 87 /******/ __webpack_require__.d = (exports, definition) => { 88 /******/ for(var key in definition) { 89 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 90 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 91 /******/ } 92 /******/ } 93 /******/ }; 94 /******/ })(); 95 /******/ 96 /******/ /* webpack/runtime/hasOwnProperty shorthand */ 97 /******/ (() => { 98 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 99 /******/ })(); 100 /******/ 101 /******/ /* webpack/runtime/make namespace object */ 102 /******/ (() => { 103 /******/ // define __esModule on exports 104 /******/ __webpack_require__.r = (exports) => { 105 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 106 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 107 /******/ } 108 /******/ Object.defineProperty(exports, '__esModule', { value: true }); 109 /******/ }; 110 /******/ })(); 111 /******/ 112 /************************************************************************/ 113 var __webpack_exports__ = {}; 114 // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk. 115 (() => { 116 /*!**************************!*\ 117 !*** ./src/pro/index.js ***! 118 \**************************/ 119 __webpack_require__.r(__webpack_exports__); 120 /* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components"); 121 /* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_0__); 122 /* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n"); 123 /* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_1__); 124 /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! moment */ "moment"); 125 /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_2__); 126 /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime"); 127 /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__); 128 129 130 const { 131 addFilter 132 } = wp.hooks; 133 134 135 addFilter('email-tracker-view-email-extra-panel', 'email-tracker/add-click-panel', (ret, state) => { 136 let click_log_panel_body; 137 if (state.total_link_click_count > 0) { 138 click_log_panel_body = /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_0__.PanelRow, { 139 children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("ol", { 140 children: state.link_click_log.map(link_click_log => { 141 if (link_click_log.date_time) { 142 let click_local_moment = moment__WEBPACK_IMPORTED_MODULE_2___default().utc(link_click_log.date_time).local(); 143 return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("li", { 144 children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_1__.sprintf)('"%s" clicked at %s on IP %s', link_click_log.link, click_local_moment.format('MMMM Do YYYY, dddd, h:mm:ss a') + ' (' + click_local_moment.fromNow() + ')', link_click_log.ip_address) 145 }); 146 } else { 147 return null; 148 } 149 }) 150 }) 151 }); 152 } else { 153 click_log_panel_body = (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_1__.__)('N/A', 'email-tracker'); 154 } 155 return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_0__.PanelBody, { 156 title: "#" + (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_1__.sprintf)((0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_1__._n)('%d time clicked', '%d times clicked', parseInt(state.total_link_click_count), 'email-tracker'), state.total_link_click_count), 157 initialOpen: state.link_click_log.length ? true : false, 158 children: click_log_panel_body 159 }); 160 }, 10, 2); 161 })(); 162 163 /******/ })() 164 ; 165 //# sourceMappingURL=index.js.map -
email-tracker/trunk/assets/package.json
r2670982 r3416646 20 20 "license": "ISC", 21 21 "devDependencies": { 22 "@wordpress/scripts": "^ 16.1.1"22 "@wordpress/scripts": "^31.1.0" 23 23 }, 24 24 "dependencies": {} -
email-tracker/trunk/assets/src/index.js
r2670982 r3416646 1 1 2 import { render, unmountComponentAtNode, Fragment, Component } from '@wordpress/element';2 import { createRoot, unmountComponentAtNode, Fragment, Component } from '@wordpress/element'; 3 3 import { ButtonGroup, Button, Dashicon, Modal, Panel, PanelRow, PanelBody, Spinner } from '@wordpress/components'; 4 4 5 5 const { applyFilters } = wp.hooks; 6 6 import apiFetch from '@wordpress/api-fetch'; 7 import { __, _n } from '@wordpress/i18n';7 import { __, _n, sprintf } from '@wordpress/i18n'; 8 8 9 9 import moment from 'moment'; … … 39 39 isLoading: false, 40 40 }); 41 42 41 42 43 43 }, (error) => { 44 44 this.setState( { … … 93 93 <PanelRow> 94 94 <ol> 95 { this.state.read_log.map( read_log => { 95 96 { this.state.read_log.map( (read_log, index) => { 96 97 let read_local_moment = moment.utc( read_log.date_time ).local(); 97 98 return ( 98 <li >99 <li key={index}> 99 100 { sprintf( __( 'Read at %s on IP %s', 'email-tracker'), read_local_moment.format( 'MMMM Do YYYY, dddd, h:mm:ss a' ) + ' (' + read_local_moment.fromNow() + ')', read_log.ip_address )} 100 101 </li> 101 102 ) 102 103 } 103 ) }104 ) } 104 105 </ol> 105 106 </PanelRow> ); … … 107 108 read_log_panel_body = __( 'N/A', 'email-tracker' ); 108 109 } 109 110 110 111 let state = this.state; 111 112 let extra_panel = applyFilters( 'email-tracker-view-email-extra-panel', null, state ); 112 113 113 114 modalBody = ( 114 115 <Fragment> … … 127 128 <PanelRow>{ moment_local_email.format( 'MMMM Do YYYY, dddd, h:mm:ss a' ) } ({ moment_local_email.fromNow() })</PanelRow> 128 129 </PanelBody> 129 { this.state.headers && 130 { this.state.headers && 130 131 <PanelBody title={ "Headers" } initialOpen={ true }> 131 132 <PanelRow>{ ( this.state.headers ) }</PanelRow> 132 133 </PanelBody> 133 134 } 134 { this.state.attachments && 135 { this.state.attachments && 135 136 <PanelBody title={ "Attachments" } initialOpen={ true }> 136 137 <PanelRow> 137 { this.state.attachments.split(",\\n").map( attachment=> {138 { this.state.attachments.split(",\\n").map( (attachment, index) => { 138 139 let attachment_url = email_tracker.content_url + attachment; 139 140 let attachment_split = attachment.split("/"); 140 141 return ( 141 <Fragment >142 <Fragment key={index}> 142 143 <a href={attachment_url} target="_blank">{attachment_split[attachment_split.length - 1]}</a> 143 144 </Fragment> … … 149 150 <PanelBody title={ "Message" } initialOpen={ true }> 150 151 <PanelRow> 151 <div dangerouslySetInnerHTML={ {__html: this.state.message}}></div>152 <div dangerouslySetInnerHTML={ { __html: this.state.message } }></div> 152 153 </PanelRow> 153 154 </PanelBody> … … 163 164 return ( 164 165 <Fragment> 165 166 { this.state.isOpen && 166 167 { this.state.isOpen && 167 168 <Modal { ...modalProps } style={{ minWidth: '75%' }} onRequestClose={ this.closeModal }> 168 169 { modalBody } … … 182 183 }; 183 184 184 const root = document.getElementById( 'emtr-email-view-modal-container' ); 185 const container = document.getElementById( 'emtr-email-view-modal-container' ); 186 const root = createRoot( container ); 185 187 186 unmountComponentAtNode( root ); 187 render( <EmailModalView {...passProps} />, root ); 188 // root.unmount(); // Unmount the component from the root 189 190 root.render( <EmailModalView {...passProps} /> ); 188 191 189 192 return false; -
email-tracker/trunk/assets/src/pro/index.js
r2670982 r3416646 1 import { __, _n } from '@wordpress/i18n';2 1 import { PanelRow, PanelBody } from '@wordpress/components'; 3 2 import { __, _n, sprintf } from '@wordpress/i18n'; 4 3 5 4 const { addFilter } = wp.hooks; -
email-tracker/trunk/composer.json
r3340406 r3416646 10 10 ], 11 11 "require": { 12 "soundasleep/html2text": "^2.0" 12 "soundasleep/html2text": "^2.0", 13 "freemius/wordpress-sdk": "^2.13" 13 14 } 14 15 } -
email-tracker/trunk/composer.lock
r2670982 r3416646 5 5 "This file is @generated automatically" 6 6 ], 7 "content-hash": " a32ca914ceef26f719b7b87c0c48b60e",7 "content-hash": "c1a7225e1319395053252465187b61ea", 8 8 "packages": [ 9 9 { 10 "name": "freemius/wordpress-sdk", 11 "version": "2.13.0", 12 "source": { 13 "type": "git", 14 "url": "https://github.com/Freemius/wordpress-sdk.git", 15 "reference": "3cbe98b5bd0b0fb5ca4df97b8088592737ea4375" 16 }, 17 "dist": { 18 "type": "zip", 19 "url": "https://api.github.com/repos/Freemius/wordpress-sdk/zipball/3cbe98b5bd0b0fb5ca4df97b8088592737ea4375", 20 "reference": "3cbe98b5bd0b0fb5ca4df97b8088592737ea4375", 21 "shasum": "" 22 }, 23 "require": { 24 "php": ">=5.6" 25 }, 26 "require-dev": { 27 "dealerdirect/phpcodesniffer-composer-installer": "^1.0", 28 "phpcompatibility/php-compatibility": "^9.3", 29 "phpcompatibility/phpcompatibility-wp": "^2.1", 30 "phpstan/extension-installer": "^1.3", 31 "squizlabs/php_codesniffer": "^3.7", 32 "szepeviktor/phpstan-wordpress": "^1.3", 33 "wp-coding-standards/wpcs": "^2.3" 34 }, 35 "type": "library", 36 "autoload": { 37 "files": [ 38 "start.php" 39 ] 40 }, 41 "notification-url": "https://packagist.org/downloads/", 42 "license": [ 43 "GPL-3.0-only" 44 ], 45 "description": "Freemius WordPress SDK", 46 "homepage": "https://freemius.com", 47 "keywords": [ 48 "freemius", 49 "plugin", 50 "sdk", 51 "theme", 52 "wordpress", 53 "wordpress-plugin", 54 "wordpress-theme" 55 ], 56 "support": { 57 "issues": "https://github.com/Freemius/wordpress-sdk/issues", 58 "source": "https://github.com/Freemius/wordpress-sdk/tree/2.13.0" 59 }, 60 "time": "2025-11-11T07:52:08+00:00" 61 }, 62 { 10 63 "name": "soundasleep/html2text", 11 "version": " 1.1.0",64 "version": "2.1.0", 12 65 "source": { 13 66 "type": "git", 14 67 "url": "https://github.com/soundasleep/html2text.git", 15 "reference": " 3243a7107878a61685d2eccf99918d6479e039fc"68 "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3" 16 69 }, 17 70 "dist": { 18 71 "type": "zip", 19 "url": "https://api.github.com/repos/soundasleep/html2text/zipball/ 3243a7107878a61685d2eccf99918d6479e039fc",20 "reference": " 3243a7107878a61685d2eccf99918d6479e039fc",72 "url": "https://api.github.com/repos/soundasleep/html2text/zipball/83502b6f8f1aaef8e2e238897199d64f284b4af3", 73 "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3", 21 74 "shasum": "" 22 75 }, … … 24 77 "ext-dom": "*", 25 78 "ext-libxml": "*", 26 "php": " >=7.0"79 "php": "^7.3|^8.0" 27 80 }, 28 81 "require-dev": { 29 "php unit/phpunit": "~7.0",30 " soundasleep/component-tests": "~0.2"82 "phpstan/phpstan": "^1.9", 83 "phpunit/phpunit": "^7.0|^8.0|^9.0" 31 84 }, 32 85 "type": "library", … … 58 111 "email": "support@jevon.org", 59 112 "issues": "https://github.com/soundasleep/html2text/issues", 60 "source": "https://github.com/soundasleep/html2text/tree/ master"113 "source": "https://github.com/soundasleep/html2text/tree/2.1.0" 61 114 }, 62 "time": "20 19-02-15T01:44:54+00:00"115 "time": "2023-01-06T09:28:15+00:00" 63 116 } 64 117 ], … … 66 119 "aliases": [], 67 120 "minimum-stability": "stable", 68 "stability-flags": [],121 "stability-flags": {}, 69 122 "prefer-stable": false, 70 123 "prefer-lowest": false, 71 "platform": [],72 "platform-dev": [],73 "plugin-api-version": "2. 0.0"124 "platform": {}, 125 "platform-dev": {}, 126 "plugin-api-version": "2.6.0" 74 127 } -
email-tracker/trunk/email-tracker-main.php
r3344738 r3416646 2 2 3 3 // Autoloading Vendor 4 $ autoloader = plugin_dir_path( EMTR_FILE ) . '/vendor/autoload.php';4 $emtr_autoloader = plugin_dir_path( EMTR_FILE ) . '/vendor/autoload.php'; 5 5 // When WordPress is loaded as composer dependecy, There will not be __DIR__/vendor/autoload.php pressent. 6 6 // so we need to check 7 if ( is_readable( $autoloader ) ) { 8 require $autoloader; 9 } 10 11 7 if ( is_readable( $emtr_autoloader ) ) { 8 require $emtr_autoloader; 9 } 12 10 require_once plugin_dir_path( EMTR_FILE ) . '/defines.php'; 13 11 require_once plugin_dir_path( EMTR_FILE ) . '/src/class-email-tracker-invoker.php'; 14 12 \PrashantWP\Email_Tracker\Email_Tracker_Invoker::register(); 15 16 13 /* 17 14 * includes all functions which required by plugin 18 15 */ 19 16 if ( is_admin() ) { 20 /*21 * Back-end (visible for admin only)22 */23 require_once EMTR_PLUGIN_PATH . 'et-admin.php';17 /* 18 * Back-end (visible for admin only) 19 */ 20 require_once EMTR_PLUGIN_PATH . 'et-admin.php'; 24 21 } 25 22 /** … … 27 24 */ 28 25 define( 'EMTR_DB_VERSION', '1.2.1' ); 29 define( 'EMTR_VERSION', '5.3.1 4' );26 define( 'EMTR_VERSION', '5.3.16' ); 30 27 /* 31 28 * Upgrade Script 32 29 */ 33 30 if ( version_compare( get_option( 'emtr_db_version' ), EMTR_DB_VERSION, '<' ) ) { 34 add_action( 'admin_init', 'emtr_create_tables', 1 ); 35 } 36 31 add_action( 'admin_init', 'emtr_create_tables', 1 ); 32 } 37 33 /** 38 34 * This function and hook set default value of setting … … 40 36 */ 41 37 function emtr_create_tables() { 42 global $wpdb; 43 require_once ABSPATH . 'wp-admin/includes/upgrade.php'; 44 45 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'email' ); 46 $charset_collate = $wpdb->get_charset_collate(); 47 48 $sql = "CREATE TABLE {$tableName} 49 ( 50 email_id int(30) unsigned NOT NULL AUTO_INCREMENT, 51 date_time datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 52 `to` varchar(255) NOT NULL DEFAULT '', 53 subject varchar(255) NOT NULL DEFAULT '', 54 message text, 55 message_plain text, 56 headers text, 57 attachments text, 58 PRIMARY KEY (email_id), 59 KEY date_time (date_time), 60 KEY `to` (`to`), 61 KEY subject (subject) 62 ) $charset_collate;"; 63 dbDelta( $sql ); 64 65 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ); 66 $sql = "CREATE TABLE {$tableName} 67 ( 68 trkemail_id int(30) unsigned NOT NULL AUTO_INCREMENT, 69 trkemail_email_id int(10) unsigned NOT NULL COMMENT 'FK (emtr_mail => email_id)', 70 trkemail_date_time datetime NOT NULL, 71 trkemail_http_user_agent varchar(255) NOT NULL, 72 trkemail_ip_address varchar(255) NOT NULL, 73 trkemail_tacked_by varchar(60) NOT NULL DEFAULT 'Image' COMMENT '[Image] , [Link]', 74 PRIMARY KEY (trkemail_id), 75 KEY trkemail_email_id (trkemail_email_id), 76 KEY trkemail_date_time (trkemail_date_time) 77 ) $charset_collate;"; 78 dbDelta( $sql ); 79 80 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ); 81 $sql = "CREATE TABLE IF NOT EXISTS {$tableName} 82 ( 83 trklink_id int(30) unsigned NOT NULL AUTO_INCREMENT, 84 trklink_user_id int(30) unsigned NOT NULL COMMENT '(FK user_master => user_id)', 85 trklink_email_id int(30) unsigned NOT NULL COMMENT 'FK (lead_mail => email_id)', 86 trklink_link varchar(255) NOT NULL, 87 PRIMARY KEY (trklink_id), 88 KEY trklink_user_id (trklink_user_id), 89 KEY trklink_email_id (trklink_email_id) 90 ) $charset_collate;"; 91 dbDelta( $sql ); 92 93 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_master' ); 94 $sql = "CREATE TABLE {$tableName} 95 ( 96 trklink_id int(30) unsigned NOT NULL AUTO_INCREMENT, 97 trklink_user_id int(30) unsigned NOT NULL COMMENT '(FK user_master => user_id)', 98 trklink_email_id int(30) unsigned NOT NULL COMMENT 'FK (lead_mail => email_id)', 99 trklink_link varchar(255) NOT NULL, 100 PRIMARY KEY (trklink_id), 101 KEY trklink_user_id (trklink_user_id), 102 KEY trklink_email_id (trklink_email_id) 103 ) $charset_collate;"; 104 dbDelta( $sql ); 105 106 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_click_log' ); 107 $sql = "CREATE TABLE IF NOT EXISTS {$tableName} 108 ( 109 trklinkclick_id int(30) unsigned NOT NULL AUTO_INCREMENT, 110 trklinkclick_trklink_id int(30) unsigned NOT NULL COMMENT 'FK (track_email_link_master => trklink_id)', 111 trklinkclick_email_id int(30) unsigned NOT NULL DEFAULT '0', 112 trklinkclick_date_time datetime NOT NULL, 113 trklinkclick_http_user_agent varchar(255) NOT NULL, 114 trklinkclick_ip_address varchar(200) NOT NULL, 115 PRIMARY KEY (trklinkclick_id), 116 KEY trklinkclick_trklink_id (trklinkclick_trklink_id), 117 KEY trklinkclick_email_id (trklinkclick_email_id) 118 ) $charset_collate;"; 119 dbDelta( $sql ); 120 121 update_option( 'emtr_db_version', EMTR_DB_VERSION ); 122 update_option( 'emtr_version', EMTR_VERSION ); 123 // For add rewite rule of email tracking 124 flush_rewrite_rules(); 125 } 126 127 function emtr_plugin_activate( $network_wide ) { 128 global $wp_rewrite; 129 $wp_rewrite->set_permalink_structure( '/%postname%/' ); 130 $wp_rewrite->flush_rules(); 131 132 if ( function_exists( 'is_multisite' ) && is_multisite() && $network_wide ) { 133 global $wpdb; 134 $old_blog = $wpdb->blogid; 135 // Get all blog ids 136 $blogids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs}" ); 137 foreach ( $blogids as $blog_id ) { 138 switch_to_blog( $blog_id ); 139 // Create database table if not exists 140 emtr_create_tables(); 141 } 142 switch_to_blog( $old_blog ); 143 return; 144 } 145 146 \PrashantWP\Email_Tracker\Util::get_factory() 147 ->get( '\PrashantWP\Email_Tracker\Admin\Email_List\Setup' ) 148 ->set_up_capability_to_administrator(); 149 150 // Create database table if not exists 151 emtr_create_tables(); 38 global $wpdb; 39 require_once ABSPATH . 'wp-admin/includes/upgrade.php'; 40 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'email' ); 41 $charset_collate = $wpdb->get_charset_collate(); 42 $sql = "CREATE TABLE {$tableName}\n (\n email_id int(30) unsigned NOT NULL AUTO_INCREMENT,\n date_time datetime NOT NULL DEFAULT '0000-00-00 00:00:00', \n `to` varchar(255) NOT NULL DEFAULT '',\n subject varchar(255) NOT NULL DEFAULT '',\n message text,\n message_plain text,\n headers text,\n attachments text,\n PRIMARY KEY (email_id),\n KEY date_time (date_time),\n KEY `to` (`to`),\n KEY subject (subject)\n ) {$charset_collate};"; 43 dbDelta( $sql ); 44 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ); 45 $sql = "CREATE TABLE {$tableName}\n (\n trkemail_id int(30) unsigned NOT NULL AUTO_INCREMENT,\n trkemail_email_id int(10) unsigned NOT NULL COMMENT 'FK (emtr_mail => email_id)',\n trkemail_date_time datetime NOT NULL,\n trkemail_http_user_agent varchar(255) NOT NULL,\n trkemail_ip_address varchar(255) NOT NULL,\n trkemail_tacked_by varchar(60) NOT NULL DEFAULT 'Image' COMMENT '[Image] , [Link]',\n PRIMARY KEY (trkemail_id),\n KEY trkemail_email_id (trkemail_email_id),\n KEY trkemail_date_time (trkemail_date_time)\n ) {$charset_collate};"; 46 dbDelta( $sql ); 47 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ); 48 $sql = "CREATE TABLE IF NOT EXISTS {$tableName}\n (\n trklink_id int(30) unsigned NOT NULL AUTO_INCREMENT,\n trklink_user_id int(30) unsigned NOT NULL COMMENT '(FK user_master => user_id)',\n trklink_email_id int(30) unsigned NOT NULL COMMENT 'FK (lead_mail => email_id)',\n trklink_link varchar(255) NOT NULL,\n PRIMARY KEY (trklink_id),\n KEY trklink_user_id (trklink_user_id),\n KEY trklink_email_id (trklink_email_id)\n ) {$charset_collate};"; 49 dbDelta( $sql ); 50 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_master' ); 51 $sql = "CREATE TABLE {$tableName}\n (\n trklink_id int(30) unsigned NOT NULL AUTO_INCREMENT,\n trklink_user_id int(30) unsigned NOT NULL COMMENT '(FK user_master => user_id)',\n trklink_email_id int(30) unsigned NOT NULL COMMENT 'FK (lead_mail => email_id)',\n trklink_link varchar(255) NOT NULL,\n PRIMARY KEY (trklink_id),\n KEY trklink_user_id (trklink_user_id),\n KEY trklink_email_id (trklink_email_id)\n ) {$charset_collate};"; 52 dbDelta( $sql ); 53 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_click_log' ); 54 $sql = "CREATE TABLE IF NOT EXISTS {$tableName}\n (\n trklinkclick_id int(30) unsigned NOT NULL AUTO_INCREMENT,\n trklinkclick_trklink_id int(30) unsigned NOT NULL COMMENT 'FK (track_email_link_master => trklink_id)',\n trklinkclick_email_id int(30) unsigned NOT NULL DEFAULT '0',\n trklinkclick_date_time datetime NOT NULL,\n trklinkclick_http_user_agent varchar(255) NOT NULL,\n trklinkclick_ip_address varchar(200) NOT NULL,\n PRIMARY KEY (trklinkclick_id),\n KEY trklinkclick_trklink_id (trklinkclick_trklink_id),\n KEY trklinkclick_email_id (trklinkclick_email_id)\n ) {$charset_collate};"; 55 dbDelta( $sql ); 56 update_option( 'emtr_db_version', EMTR_DB_VERSION ); 57 update_option( 'emtr_version', EMTR_VERSION ); 58 // For add rewite rule of email tracking 59 flush_rewrite_rules(); 60 } 61 62 function emtr_plugin_activate( $network_wide ) { 63 global $wp_rewrite; 64 $wp_rewrite->set_permalink_structure( '/%postname%/' ); 65 $wp_rewrite->flush_rules(); 66 if ( function_exists( 'is_multisite' ) && is_multisite() && $network_wide ) { 67 global $wpdb; 68 $old_blog = $wpdb->blogid; 69 // Get all blog ids 70 $blogids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs}" ); 71 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 72 foreach ( $blogids as $blog_id ) { 73 switch_to_blog( $blog_id ); 74 // Create database table if not exists 75 emtr_create_tables(); 76 } 77 switch_to_blog( $old_blog ); 78 return; 79 } 80 \PrashantWP\Email_Tracker\Util::get_factory()->get( '\\PrashantWP\\Email_Tracker\\Admin\\Email_List\\Setup' )->set_up_capability_to_administrator(); 81 // Create database table if not exists 82 emtr_create_tables(); 152 83 } 153 84 154 85 register_activation_hook( EMTR_BASE_FILE_PATH, 'emtr_plugin_activate' ); 155 156 86 function emtr_uninstall_cleanup() { 157 require_once EMTR_PLUGIN_PATH . '/emtr-uninstall.php';87 require_once EMTR_PLUGIN_PATH . '/emtr-uninstall.php'; 158 88 } 159 89 160 90 emtr()->add_action( 'after_uninstall', 'emtr_uninstall_cleanup' ); 161 162 function emtr_email_before_send( $orig_email ) { 163 // multiple email address 164 if ( is_string( $orig_email['to'] ) && false !== stripos( $orig_email['to'], ',' ) ) { 165 return $orig_email; 166 } 167 // multiple email address 168 if ( is_array( $orig_email['to'] ) ) { 169 return $orig_email; 170 } 171 172 global $wpdb; 173 174 if ( false === stripos( $orig_email['message'], '</' ) ) { 175 $orig_email['message'] = str_replace( array( '<', '>' ), '', $orig_email['message'] ); 91 function emtr_email_before_send( $orig_email ) { 92 /* 93 echo '<pre>'; 94 var_dump( $orig_email ); 95 die; 96 */ 97 // multiple email address 98 if ( is_string( $orig_email['to'] ) && false !== stripos( $orig_email['to'], ',' ) ) { 99 return $orig_email; 100 } 101 // multiple email address 102 if ( is_array( $orig_email['to'] ) ) { 103 return $orig_email; 104 } 105 global $wpdb; 106 if ( false === stripos( $orig_email['message'], '</' ) ) { 107 $orig_email['message'] = str_replace( array('<', '>'), '', $orig_email['message'] ); 176 108 $orig_email['message'] = nl2br( $orig_email['message'] ); 177 109 } 178 179 if ( function_exists( 'make_clickable' ) ) { 180 $orig_email['message'] = make_clickable( $orig_email['message'] ); 181 } 182 183 $email = $orig_email; 184 185 require_once EMTR_PLUGIN_PATH . 'vendor/autoload.php'; 186 $message_plain = ''; 187 188 // Suppress deprecation warnings from the html2text library 189 $old_error_level = error_reporting(); 190 error_reporting($old_error_level & ~E_DEPRECATED); 191 192 try { 193 $message_plain = \Soundasleep\Html2Text::convert( $email['message'], array( 194 'ignore_errors' => true, 195 ) ); 196 } catch ( Exception $e ) { 197 // silently hide 198 } catch ( Error $e ) { 199 // silently hide 200 } 201 202 // Restore original error reporting level 203 error_reporting($old_error_level); 204 $email_db_data = array( 205 'to' => emtr_extract_email_field( $email['to'] ), 206 'subject' => $email['subject'], 207 'message' => $email['message'], 208 'message_plain' => $message_plain, 209 'headers' => emtr_extract_email_field( $email['headers'] ), 210 'attachments' => \PrashantWP\Email_Tracker\Util::emtr_extract_attachments( $email['attachments'] ), 211 'date_time' => gmdate( 'Y-m-d H:i:s' ), 212 ); 213 $ret = $wpdb->insert( 214 \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'email' ), 215 $email_db_data, 216 array( 217 '%s', 218 '%s', 219 '%s', 220 '%s', 221 '%s', 222 '%s', 223 '%s', 224 ) 225 ); 226 227 $model_trackemail = \PrashantWP\Email_Tracker\Factory::get( '\PrashantWP\Email_Tracker\Model\TrackEmail' ); 228 if ( $ret ) { 229 $email_id = $wpdb->insert_id; 230 if ( emtr()->is__premium_only() ) { 231 if ( emtr()->is_plan( 'pro', true ) || emtr()->is_trial() ) { 232 $orig_email['message'] = $model_trackemail->email_link_replace( $orig_email['message'], $email_id, get_current_user_id() ); 233 } 234 } 235 $orig_email['message'] .= $model_trackemail->get_track_code( $email_id ); 236 } 237 238 if ( emtr()->is__premium_only() ) { 239 // Debug Message 240 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { 241 $str = esc_html__( 'To :', 'email-tracker' ) . htmlspecialchars( $email_db_data['to'] ) . '<br>' . __( 'Subject :', 'email-tracker' ) . esc_html( $email['subject'] ) . '<br>' . __( 'Headers :', 'email-tracker' ) . htmlspecialchars( $email_db_data['headers'] ) . '<br>' . __( 'Attachments :', 'email-tracker' ) . nl2br( $email_db_data['attachments'] ) . '<br>' . __( 'Message :', 'email-tracker' ) . $orig_email['message'] . '<br>'; 242 $str = '<b>To :</b><br/>' . htmlspecialchars( $email_db_data['to'] ) . '<br><br> 243 <b>Subject :</b><br/>' . $email_db_data['subject'] . '<br><br>'; 244 $str .= '<b>' . esc_html__( 'Date :', 'email-tracker' ) . '</b><br/>' . get_date_from_gmt( $email_db_data['date_time'], 'F j, Y g:i A' ) . \PrashantWP\Email_Tracker\Util::emtr_relative_time( get_date_from_gmt( $email_db_data['date_time'] ) ) . '<br><br>'; 245 if ( ! empty( $email_db_data['headers'] ) ) { 246 $str .= '<b>' . esc_html__( 'Headers :', 'email-tracker' ) . '</b><br/>' . nl2br( $email_db_data['headers'] ) . '<br><br>'; 247 } 248 249 if ( ! empty( $email_db_data['attachments'] ) ) { 250 $arr_attachments = explode( ',\\n', $email_db_data['attachments'] ); 251 $str_attach = ''; 252 foreach ( $arr_attachments as $key => $attach ) { 253 $str_attach .= '<a href="' . esc_url( WP_CONTENT_URL . $attach ) . '" target="_blank">' . WP_CONTENT_URL . $attach . '</a>'; 254 if ( $key != count( $arr_attachments ) - 1 ) { 255 $str_attach .= ',<br/>'; 256 } 257 } 258 $str .= '<b>' . esc_html__( 'Attachments :', 'email-tracker' ) . '</b><br/>' . $str_attach . '<br><br>'; 259 } 260 261 $str .= '<b>' . esc_html__( 'Message :', 'email-tracker' ) . '</b><br/>' . $orig_email['message'] . '<br><br>'; 262 $upload_dir = wp_upload_dir(); 263 $email_dir = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'email_output'; 264 265 // Delete file older than 1 day 266 // if ( $handle = opendir( $email_dir ) ) { 267 // while ( false !== ( $file = readdir( $handle ) ) ) { 268 // if ( in_array( $file, array( '.', '..', '.DS_Store' ) ) ) { 269 // continue; 270 // } 271 // echo $email_dir . $file; 272 // echo "<br>"; 273 // email_outputemail-2021-05-14-06-13-54-0.53941100 1620972834.html 274 275 // $filelastmodified = filemtime( $email_dir . $file ); 276 // 24 hours in a day * 3600 seconds per hour 277 // if( ( time() - $filelastmodified ) > 120 ) 278 // { 279 // @unlink( $email_dir . $file ); 280 // } 281 282 // } 283 // closedir($handle); 284 // } 285 286 wp_mkdir_p( $email_dir ); 287 // TO DO 288 file_put_contents( $email_dir . DIRECTORY_SEPARATOR . 'email-' . date( 'Y-m-d-H-i-s' ) . '.html', $str ); 289 } 290 } 291 292 return $orig_email; 110 if ( function_exists( 'make_clickable' ) ) { 111 $orig_email['message'] = make_clickable( $orig_email['message'] ); 112 } 113 $email = $orig_email; 114 require_once EMTR_PLUGIN_PATH . 'vendor/autoload.php'; 115 $message_plain = ''; 116 // Suppress deprecation warnings from the html2text library 117 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting -- To suppress the error. 118 $old_error_level = error_reporting(); 119 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting -- To suppress the error. 120 error_reporting( $old_error_level & ~E_DEPRECATED ); 121 try { 122 $message_plain = \Soundasleep\Html2Text::convert( $email['message'], array( 123 'ignore_errors' => true, 124 ) ); 125 } catch ( Exception $e ) { 126 // silently hide 127 } catch ( Error $e ) { 128 // silently hide 129 } 130 // Restore original error reporting level 131 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting -- To suppress the error. 132 error_reporting( $old_error_level ); 133 $email_db_data = array( 134 'to' => emtr_extract_email_field( $email['to'] ), 135 'subject' => $email['subject'], 136 'message' => $email['message'], 137 'message_plain' => $message_plain, 138 'headers' => emtr_extract_email_field( $email['headers'] ), 139 'attachments' => \PrashantWP\Email_Tracker\Util::emtr_extract_attachments( $email['attachments'] ), 140 'date_time' => gmdate( 'Y-m-d H:i:s' ), 141 ); 142 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery 143 $ret = $wpdb->insert( \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'email' ), $email_db_data, array( 144 '%s', 145 '%s', 146 '%s', 147 '%s', 148 '%s', 149 '%s', 150 '%s' 151 ) ); 152 $model_trackemail = \PrashantWP\Email_Tracker\Factory::get( '\\PrashantWP\\Email_Tracker\\Model\\TrackEmail' ); 153 if ( $ret ) { 154 $email_id = $wpdb->insert_id; 155 $orig_email['message'] .= $model_trackemail->get_track_code( $email_id ); 156 } 157 return $orig_email; 293 158 } 294 159 295 160 add_filter( 'wp_mail', 'emtr_email_before_send', PHP_INT_MAX ); 296 297 function emtr_extract_email_field( $email_field ) { 298 return ( is_array( $email_field ) ? implode( ', ', $email_field ) : $email_field ); 299 } 300 301 function emtr_pre_wp_mail( $ret, $atts ) { 302 $forbid_mail = false; 303 304 // error_log( '$atts: ' . var_export( $atts, true ) ); 305 306 // multiple email address 307 if ( is_string( $atts['to'] ) && false !== stripos( $atts['to'], ',' ) ) { 308 $forbid_mail = true; 309 $to_arr = explode( ',', $atts['to'] ); 310 } 311 // multiple email address 312 if ( is_array( $atts['to'] ) ) { 313 $forbid_mail = true; 314 $to_arr = $atts['to']; 315 } 316 317 if ( $forbid_mail ) { 318 $to_arr = array_map( 'trim', $to_arr ); 319 $to_arr = array_filter( $to_arr ); 320 321 if ( ! isset( $atts['headers'] ) ) { 322 $atts['headers'] = ''; 323 } 324 if ( ! isset( $atts['attachments'] ) ) { 325 $atts['attachments'] = array(); 326 } 327 328 foreach ( $to_arr as $to ) { 329 wp_mail( $to, $atts['subject'], $atts['message'], $atts['headers'], $atts['attachments'] ); 330 } 331 return $forbid_mail; 332 } 333 334 return $ret; 335 } 336 add_filter( 'pre_wp_mail', 'emtr_pre_wp_mail', 10, 2 ); 337 338 339 161 function emtr_extract_email_field( $email_field ) { 162 return ( is_array( $email_field ) ? implode( ', ', $email_field ) : $email_field ); 163 } 164 165 function emtr_pre_wp_mail( $ret, $atts ) { 166 $forbid_mail = false; 167 // multiple email address 168 if ( is_string( $atts['to'] ) && false !== stripos( $atts['to'], ',' ) ) { 169 $forbid_mail = true; 170 $to_arr = explode( ',', $atts['to'] ); 171 } 172 // multiple email address 173 if ( is_array( $atts['to'] ) ) { 174 $forbid_mail = true; 175 $to_arr = $atts['to']; 176 } 177 if ( $forbid_mail ) { 178 $to_arr = array_map( 'trim', $to_arr ); 179 $to_arr = array_filter( $to_arr ); 180 if ( !isset( $atts['headers'] ) ) { 181 $atts['headers'] = ''; 182 } 183 if ( !isset( $atts['attachments'] ) ) { 184 $atts['attachments'] = array(); 185 } 186 foreach ( $to_arr as $to ) { 187 wp_mail( 188 $to, 189 $atts['subject'], 190 $atts['message'], 191 $atts['headers'], 192 $atts['attachments'] 193 ); 194 } 195 return $forbid_mail; 196 } 197 return $ret; 198 } 199 200 add_filter( 201 'pre_wp_mail', 202 'emtr_pre_wp_mail', 203 10, 204 2 205 ); 340 206 /** 341 207 * Filter the mail content type. 342 208 */ 343 209 add_filter( 'wp_mail_content_type', 'emtr_set_html_mail_content_type', PHP_INT_MAX - 10 ); 344 function emtr_set_html_mail_content_type( $content_type ) { 345 global $emtr_is_plain; 346 347 if ( $content_type == 'text/plain' ) { 348 $emtr_is_plain = true; 349 return 'text/html'; 350 } else { 351 $emtr_is_plain = false; 352 return $content_type; 353 } 354 } 355 356 function emtr_custom_rewrite_basic( $wp_rewrite ) { 357 $new_rules = array( 358 '^track/e/(o|l)/([^/]+).*$' => 'index.php?main_action=track-email.php&action=$matches[1]&pk=$matches[2]', 359 ); 360 $wp_rewrite->rules = $new_rules + $wp_rewrite->rules; 210 function emtr_set_html_mail_content_type( $content_type ) { 211 global $emtr_is_plain; 212 if ( $content_type == 'text/plain' ) { 213 $emtr_is_plain = true; 214 return 'text/html'; 215 } else { 216 $emtr_is_plain = false; 217 return $content_type; 218 } 219 } 220 221 function emtr_custom_rewrite_basic( $wp_rewrite ) { 222 $new_rules = array( 223 '^track/e/(o|l)/([^/]+).*$' => 'index.php?main_action=track-email.php&action=$matches[1]&pk=$matches[2]', 224 ); 225 $wp_rewrite->rules = $new_rules + $wp_rewrite->rules; 361 226 } 362 227 363 228 add_action( 'generate_rewrite_rules', 'emtr_custom_rewrite_basic' ); 364 function query_vars( $public_query_vars) {365 $public_query_vars[] = 'main_action';366 $public_query_vars[]= 'action';367 $public_query_vars[]= 'pk';368 return $public_query_vars;369 } 370 371 add_filter( 'query_vars', ' query_vars' );229 function emtr_query_vars( $public_query_vars ) { 230 $public_query_vars[] = 'main_action'; 231 $public_query_vars[] = 'action'; 232 $public_query_vars[] = 'pk'; 233 return $public_query_vars; 234 } 235 236 add_filter( 'query_vars', 'emtr_query_vars' ); 372 237 add_action( 'parse_request', 'emtr_parse_request' ); 373 function emtr_parse_request( &$wp ) { 374 if ( array_key_exists( 'main_action', $wp->query_vars ) ) { 375 set_query_var( 'action', $wp->query_vars['action'] ); 376 set_query_var( 'pk', $wp->query_vars['pk'] ); 377 include EMTR_PLUGIN_PATH . 'track-email.php'; 378 exit; 379 } 380 381 } 382 383 /* 384 add_filter( 385 'retrieve_password_message', 386 'emtr_retrieve_password_message', 387 PHP_INT_MAX - 20, 388 2 389 ); 390 function emtr_retrieve_password_message( $message, $key ) { 391 $message = str_replace( array( '<', '>' ), '', $message ); 392 return $message; 393 } 394 */ 395 396 if ( emtr()->is__premium_only() ) { 397 398 if ( emtr()->is_plan( 'pro', true ) || emtr()->is_trial() ) { 399 add_filter( 'emtr_upgrade_notice', 'emtr_upgrade_notice_remove', 10 ); 400 function emtr_upgrade_notice_remove( $str ) { 401 return ''; 402 } 403 } 238 function emtr_parse_request( &$wp ) { 239 if ( array_key_exists( 'main_action', $wp->query_vars ) ) { 240 set_query_var( 'action', $wp->query_vars['action'] ); 241 set_query_var( 'pk', $wp->query_vars['pk'] ); 242 include EMTR_PLUGIN_PATH . 'track-email.php'; 243 exit; 244 } 404 245 } 405 246 … … 413 254 */ 414 255 class Emtr_Mailer { 415 416 /** 417 * @var string 418 */ 419 protected $previous_altbody; 420 /** 421 * Add hooks 422 */ 423 public function add_hooks() { 424 // add action so function actually runs 425 add_action( 'phpmailer_init', array( $this, 'set_plaintext_body' ) ); 426 } 427 428 /** 429 * @param PHPMailer $phpmailer 430 */ 431 public function set_plaintext_body( $phpmailer ) { 432 // don't run if sending plain text email already 433 if ( $phpmailer->ContentType === 'text/plain' ) { 434 return; 435 } 436 // don't run if altbody is set (by other plugin) 437 if ( ! empty( $phpmailer->AltBody ) && $phpmailer->AltBody !== $this->previous_altbody ) { 438 return; 439 } 440 // set AltBody 441 $text_message = $this->strip_html_tags( $phpmailer->Body ); 442 $phpmailer->AltBody = $text_message; 443 $this->previous_altbody = $text_message; 444 } 445 446 /** 447 * Remove HTML tags, including invisible text such as style and 448 * script code, and embedded objects. Add line breaks around 449 * block-level tags to prevent word joining after tag removal. 450 */ 451 private function strip_html_tags( $text ) { 452 $text = preg_replace( 453 array( 454 // Remove invisible content 455 '@<head[^>]*?>.*?</head>@siu', 456 '@<style[^>]*?>.*?</style>@siu', 457 '@<script[^>]*?.*?</script>@siu', 458 '@<object[^>]*?.*?</object>@siu', 459 '@<embed[^>]*?.*?</embed>@siu', 460 '@<noscript[^>]*?.*?</noscript>@siu', 461 '@<noembed[^>]*?.*?</noembed>@siu', 462 '@\\t+@siu', 463 '@\\n+@siu', 464 ), 465 '', 466 $text 467 ); 468 // replace certain elements with a line-break 469 $text = preg_replace( array( '@</?((div)|(h[1-9])|(/tr)|(p)|(pre))@iu' ), "\n\$0", $text ); 470 // replace other elements with a space 471 $text = preg_replace( array( '@</((td)|(th))@iu' ), ' $0', $text ); 472 // strip all remaining HTML tags 473 $text = strip_tags( $text ); 474 // trim text 475 $text = trim( $text ); 476 return $text; 477 } 478 479 } 256 /** 257 * @var string 258 */ 259 protected $previous_altbody; 260 261 /** 262 * Add hooks 263 */ 264 public function add_hooks() { 265 // add action so function actually runs 266 add_action( 'phpmailer_init', array($this, 'set_plaintext_body') ); 267 } 268 269 /** 270 * @param PHPMailer $phpmailer 271 */ 272 public function set_plaintext_body( $phpmailer ) { 273 // don't run if sending plain text email already 274 if ( $phpmailer->ContentType === 'text/plain' ) { 275 return; 276 } 277 // don't run if altbody is set (by other plugin) 278 if ( !empty( $phpmailer->AltBody ) && $phpmailer->AltBody !== $this->previous_altbody ) { 279 return; 280 } 281 // set AltBody 282 $text_message = $this->strip_html_tags( $phpmailer->Body ); 283 $phpmailer->AltBody = $text_message; 284 $this->previous_altbody = $text_message; 285 } 286 287 /** 288 * Remove HTML tags, including invisible text such as style and 289 * script code, and embedded objects. Add line breaks around 290 * block-level tags to prevent word joining after tag removal. 291 */ 292 private function strip_html_tags( $text ) { 293 $text = preg_replace( array( 294 // Remove invisible content 295 '@<head[^>]*?>.*?</head>@siu', 296 '@<style[^>]*?>.*?</style>@siu', 297 '@<script[^>]*?.*?</script>@siu', 298 '@<object[^>]*?.*?</object>@siu', 299 '@<embed[^>]*?.*?</embed>@siu', 300 '@<noscript[^>]*?.*?</noscript>@siu', 301 '@<noembed[^>]*?.*?</noembed>@siu', 302 '@\\t+@siu', 303 '@\\n+@siu', 304 ), '', $text ); 305 // replace certain elements with a line-break 306 $text = preg_replace( array('@</?((div)|(h[1-9])|(/tr)|(p)|(pre))@iu'), "\n\$0", $text ); 307 // replace other elements with a space 308 $text = preg_replace( array('@</((td)|(th))@iu'), ' $0', $text ); 309 // strip all remaining HTML tags 310 $text = wp_strip_all_tags( $text ); 311 // trim text 312 $text = trim( $text ); 313 return $text; 314 } 315 316 } 317 480 318 $Emtr_Mailer = new Emtr_Mailer(); 481 319 $Emtr_Mailer->add_hooks(); -
email-tracker/trunk/email-tracker.php
r3344738 r3416646 4 4 * Plugin URI: https://wordpress.org/plugins/email-tracker/ 5 5 * Description: Email Tracker is a WordPress plugin that lets you know if the emails you have sent have been read or not. 6 * Version: 5.3.15 7 * Update URI: https://api.freemius.com 8 * Author: Email Expert - Email Tracker - Track Email Open (read) and Click - Mail Tracking 9 * Requires at least: 4.0 10 * Requires PHP: 5.6.0 6 * Version: 5.3.16 7 * Author: pmbaldha 8 * Requires at least: 5.6.0 9 * Requires PHP: 7.2 11 10 * Text Domain: email-tracker 12 11 * Domain Path: /languages … … 28 27 * along with Email Tracker. If not, see <http://www.gnu.org/licenses/>. 29 28 * 30 * @fs_premium_only /src/admin/settings/ 31 */ 29 */ 32 30 33 31 namespace PrashantWP\Email_Tracker; … … 38 36 39 37 if ( function_exists( 'emtr' ) ) { 40 emtr()->set_basename( true, __FILE__ );38 emtr()->set_basename( false, __FILE__ ); 41 39 } else { 42 40 // DO NOT REMOVE THIS IF, IT IS ESSENTIAL FOR THE `function_exists` CALL ABOVE TO PROPERLY WORK. -
email-tracker/trunk/emtr-uninstall.php
r2670982 r3416646 1 <?php 1 <?php // phpcs:ignoreFile 2 2 /** 3 3 * To delete plugin … … 22 22 */ 23 23 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'email' ); 24 $wpdb->query( "DROP TABLE IF EXISTS `$tableName`" ); 24 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- No need of wpdb prepare statement. 25 $wpdb->query( "DROP TABLE IF EXISTS {$tableName};" ); 26 27 /** 28 * Delete email track database table 29 */ 30 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ); 31 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- No need of wpdb prepare statement. 32 $wpdb->query( "DROP TABLE IF EXISTS {$tableName};" ); 33 34 /** 35 * Delete email track_email_link_master database table 36 */ 37 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_master' ); 38 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- No need of wpdb prepare statement. 39 $wpdb->query( "DROP TABLE IF EXISTS {$tableName};" ); 40 41 /** 42 * Delete email track_email_link_master database table 43 */ 44 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_click_log' ); 45 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- No need of wpdb prepare statement. 46 $wpdb->query( "DROP TABLE IF EXISTS {$tableName};" ); 25 47 26 48 /** … … 28 50 */ 29 51 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ); 30 $wpdb->query( "DROP TABLE IF EXISTS `$tableName`" ); 31 32 /** 33 * Delete email track_email_link_master database table 34 */ 35 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_master' ); 36 $wpdb->query( "DROP TABLE IF EXISTS `$tableName`" ); 37 38 /** 39 * Delete email track_email_link_master database table 40 */ 41 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_click_log' ); 42 $wpdb->query( "DROP TABLE IF EXISTS `$tableName`" ); 43 44 /** 45 * Delete email track database table 46 */ 47 $tableName = \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ); 48 $wpdb->query( "DROP TABLE IF EXISTS `$tableName`" ); 52 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- No need of wpdb prepare statement. 53 $wpdb->query( "DROP TABLE IF EXISTS {$tableName};" ); 49 54 50 55 /** 51 56 * Delete email list per page screen option value 52 57 */ 53 $wpdb->query( 'DELETE FROM ' . $wpdb->prefix . "usermeta WHERE meta_key='emtr_emails_per_page'" ); 58 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- No need of wpdb prepare statement. 59 $wpdb->query( "DELETE FROM " . $wpdb->prefix . "usermeta WHERE meta_key='emtr_emails_per_page'" ); 54 60 55 61 delete_option( \PrashantWP\Email_Tracker\Util::get_factory()->get( '\PrashantWP\Email_Tracker\Options' )->get_option_name() ); … … 62 68 } 63 69 64 $ all_roles = $GLOBALS['wp_roles']->role_names;65 foreach ( $all_roles as $role_key => $role_val ) {66 $ret = wp_roles()->remove_cap( $ role_key, EMTR_MANAGE_ALL_EMAILS_CAP );70 $emtr_all_roles = $GLOBALS['wp_roles']->role_names; 71 foreach ($emtr_all_roles as $emtr_role_key => $role_val ) { 72 $ret = wp_roles()->remove_cap( $emtr_role_key, EMTR_MANAGE_ALL_EMAILS_CAP ); 67 73 } 68 74 … … 72 78 $old_blog = $wpdb->blogid; 73 79 // Get all blog ids 74 $blogids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs");80 $blogids = $wpdb->get_col( "SELECT blog_id FROM " . $wpdb->blogs ); 75 81 foreach ( $blogids as $blog_id ) { 76 82 switch_to_blog( $blog_id ); -
email-tracker/trunk/et-admin.php
r2670982 r3416646 45 45 46 46 function emtr_render_compose_email() { 47 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 47 48 if ( 'POST' == $_SERVER['REQUEST_METHOD'] && ! empty( $_POST['action'] ) && $_POST['action'] == 'emtr_send_mail' && wp_verify_nonce( $_POST['_wpnonce'], 'emtr_compose_email' ) ) { 48 49 49 50 if ( isset( $_POST['to'] ) ) { 50 $to = sanitize_text_field( $_POST['to']);51 $to = sanitize_text_field( wp_unslash( $_POST['to'] ) ); 51 52 } 52 53 if ( isset( $_POST['subject'] ) ) { 53 $subject = sanitize_text_field( $_POST['subject']);54 $subject = sanitize_text_field( wp_unslash( $_POST['subject'] ) ); 54 55 } 55 56 if ( isset( $_POST['message'] ) ) { 56 57 // message may be content of html tags 57 $message = wp_kses_post( $_POST['message']);58 $message = wp_kses_post( wp_unslash( $_POST['message'] ) ); 58 59 } 59 60 60 61 $arr_attachments = array(); 61 62 if ( isset( $_POST['attachments'] ) ) { 62 $arr_attachments_url = explode( ',', $_POST['attachments'] ); 63 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized in next line. 64 $arr_attachments_url = explode( ',', wp_unslash( $_POST['attachments'] ) ); 63 65 $arr_attachments_url = array_map( 'sanitize_text_field', $arr_attachments_url ); 64 66 $arr_attachments = array(); … … 173 175 wp_enqueue_style( 'emtr_compose_email_css', plugins_url( 'css/compose_email.css', EMTR_BASE_FILE_PATH ), array(), '0.1', 'all' ); 174 176 wp_enqueue_media(); 175 wp_enqueue_script( 'media_lib_uploader_js', plugins_url( 'js/media-lib-uploader.js', EMTR_BASE_FILE_PATH ), array( 'jquery' ), true);177 wp_enqueue_script( 'media_lib_uploader_js', plugins_url( 'js/media-lib-uploader.js', EMTR_BASE_FILE_PATH ), array( 'jquery' ), '5.3.16', array( 'strategy' => 'defer', 'in_footer' => true ) ); 176 178 } 177 179 } … … 180 182 /* To resolve header already sent error */ 181 183 function emtr_output_buffer_start() { 182 if ( isset( $_GET['page'] ) && $_GET['page'] == 'emtr_email_list' 184 if ( isset( $_GET['page'] ) && $_GET['page'] == 'emtr_email_list' // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no need of nonce verification here. 183 185 && 184 186 ( 185 ( isset( $_GET['action'] ) && $_GET['action'] == 'delete' ) 187 ( isset( $_GET['action'] ) && $_GET['action'] == 'delete' ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no need of nonce verification here. 186 188 || 187 ( isset( $_GET['action2'] ) && $_GET['action2'] == 'delete' ) 189 ( isset( $_GET['action2'] ) && $_GET['action2'] == 'delete' ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no need of nonce verification here. 188 190 ) 189 191 ) { -
email-tracker/trunk/readme.txt
r3344738 r3416646 1 === Email Tracker - Email Log, Email Open Tracking, Email Analytics & Email Management for WordPress Emails ===2 Contributors: pmbaldha, woocommerce9, emailemailemail, wordpressdotorg, woocommerce,nikunj8866, freemius1 === Email Tracker == 2 Contributors: pmbaldha, nikunj8866, freemius 3 3 Tags: email, emails, email tracking, email log, email analytics 4 Requires at least: 5. 05 Tested up to: 6. 86 Stable tag: 5.3.1 54 Requires at least: 5.6.0 5 Tested up to: 6.9 6 Stable tag: 5.3.16 7 7 License: GPLv3 or later 8 8 License URI: https://www.gnu.org/licenses/gpl-3.0.html … … 158 158 **And many more!** Email Tracker works with any WordPress plugin that uses the standard wp_mail() function to send emails. 159 159 160 = SMTP & Email Delivery Plugins: = 161 Email Tracker seamlessly integrates with all major SMTP and email delivery plugins for enhanced email reliability and tracking: 162 163 * [WP Mail SMTP](https://wordpress.org/plugins/wp-mail-smtp/) - Perfect compatibility for tracking emails sent through any SMTP service (SendGrid, Mailgun, Amazon SES, Gmail SMTP, and more) 164 * [Post SMTP Mailer/Email Log](https://wordpress.org/plugins/post-smtp/) - Full tracking support for all Post SMTP delivered emails with complete logging 165 * [Easy WP SMTP](https://wordpress.org/plugins/easy-wp-smtp/) - Track all emails sent through your configured SMTP servers 166 * [FluentSMTP](https://wordpress.org/plugins/fluent-smtp/) - Monitor emails delivered through multiple SMTP connections 167 * [MailPoet SMTP](https://wordpress.org/plugins/mailpoet/) - Track transactional emails sent via MailPoet's sending service 168 * [SendGrid](https://wordpress.org/plugins/sendgrid-email-delivery-simplified/) - Full tracking for emails delivered through SendGrid API 169 * [Mailgun for WordPress](https://wordpress.org/plugins/mailgun/) - Monitor all Mailgun API delivered emails 170 * [SparkPost](https://wordpress.org/plugins/sparkpost/) - Track emails sent through SparkPost email delivery service 171 * [Amazon SES](https://wordpress.org/plugins/wp-ses/) - Complete tracking for AWS SES delivered emails 172 * [Sendinblue](https://wordpress.org/plugins/mailin/) - Track all Sendinblue/Brevo transactional emails 173 174 = Newsletter & Email Marketing Plugins: = 175 Track and monitor all your email marketing campaigns and newsletters: 176 177 * [MailPoet](https://wordpress.org/plugins/mailpoet/) - Track newsletter opens, automated emails, and welcome series 178 * [Newsletter](https://wordpress.org/plugins/newsletter/) - Monitor all newsletter campaigns and subscriber emails 179 * [MailChimp for WordPress](https://wordpress.org/plugins/mailchimp-for-wp/) - Track opt-in confirmations and automated emails 180 * [Email Subscribers & Newsletters](https://wordpress.org/plugins/email-subscribers/) - Full tracking for broadcast emails and auto-responders 181 * [The Newsletter Plugin](https://wordpress.org/plugins/newsletter/) - Track all newsletter sends and automated workflows 182 * [SendPress Newsletters](https://wordpress.org/plugins/sendpress/) - Monitor email campaigns and subscriber notifications 183 * [MailOptin](https://wordpress.org/plugins/mailoptin/) - Track lead generation emails and autoresponders 184 * [Jackmail](https://wordpress.org/plugins/jackmail-newsletters/) - Full email tracking for all campaign sends 185 * [Noptin](https://wordpress.org/plugins/newsletter-optin-box/) - Track newsletter broadcasts and automation emails 186 * [FluentCRM](https://wordpress.org/plugins/fluent-crm/) - Monitor all CRM emails, campaigns, and sequences 187 188 **Why Email Tracker Works Perfectly with SMTP & Newsletter Plugins:** 189 * **Universal Compatibility** - Email Tracker hooks into WordPress's core wp_mail() function, ensuring compatibility with any properly coded email plugin 190 * **No Configuration Required** - Simply activate Email Tracker alongside your SMTP or newsletter plugin - tracking starts automatically 191 * **Enhanced Analytics** - Combine the delivery reliability of SMTP plugins with Email Tracker's powerful open and click tracking 192 * **Complete Email Visibility** - Track both transactional emails (via SMTP) and marketing emails (via newsletter plugins) in one dashboard 193 * **Zero Performance Impact** - Email Tracker adds tracking without affecting your SMTP service or newsletter sending speed 194 160 195 = Credits = 161 196 … … 173 208 * email tracker (incorrect) 174 209 * Email traker (incorrect) 210 * Email email track (incorrect) 175 211 * Email tracer (incorrect) 176 212 * Mail Tracker (incorrect) … … 182 218 * Mail traker (incorrect) 183 219 * Mail tracer (incorrect) 220 * Email tracer (incorrect) 221 * Trace email (incorrect) 222 * Trace mail (incorrect) 223 * Trace emails (incorrect) 224 * Trace mails (incorrect) 225 184 226 185 227 == Installation == … … 380 422 381 423 == Changelog == 424 425 = 5.3.16, December 10, 2025 = 426 * SECURITY: The Email Tracker plugin was vulnerable to SQL Injection via the 'orderby' parameter in all versions up to, and including, 5.3.12 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. The issue was fixed. 427 * TWEAK: The Freemius library has put in the vendor folder. 428 * TWEAK: Defer strategy and footer enque media upload JavaScript file in the compose email admin page. 429 * TWEAK: Replace date() with gmdate() function. 430 * COMPATIBILITY: Updated to html2Text lib to version 2.1.0. 431 * COMPATIBILITY: Replace _e() with esc_html_e() for compatibility with the Plugin Check plugin. 432 * COMPATIBILITY: Fix errors and warnings of the Plugin Check plugin. 382 433 383 434 = 5.3.15, August 15, 2025 = -
email-tracker/trunk/src/admin/class-email-tracker-admin.php
r3344738 r3416646 1 1 <?php 2 2 3 namespace PrashantWP\Email_Tracker\Admin; 3 4 4 if ( ! defined( 'ABSPATH' ) ) {5 exit;5 if ( !defined( 'ABSPATH' ) ) { 6 exit; 6 7 } 7 8 8 use Exception; 9 9 final class Email_Tracker_Admin extends \PrashantWP\Email_Tracker\Base { 10 11 10 /** 12 * Self class instance13 *14 * @var object15 */16 private static $instance;11 * Self class instance 12 * 13 * @var object 14 */ 15 private static $instance; 17 16 18 17 public function __construct() { … … 21 20 22 21 public static function register() { 23 if ( ! isset( self::$instance ) ) {22 if ( !isset( self::$instance ) ) { 24 23 self::$instance = new self(); 25 26 24 self::$instance->set_up_email_list(); 27 if ( emtr()->is__premium_only() ) {28 self::$instance->set_up_settings__premium_only();29 }30 25 } 31 26 } 32 27 33 28 public function set_up_email_list() { 34 $this->factory 35 ->get( '\PrashantWP\Email_Tracker\Admin\Email_List\Setup' ) 36 ->init(); 29 $this->factory->get( '\\PrashantWP\\Email_Tracker\\Admin\\Email_List\\Setup' )->init(); 37 30 } 38 31 39 public function set_up_settings__premium_only() {40 ( new Settings\Setup() )->init();41 }42 32 } -
email-tracker/trunk/src/admin/email-list/class-setup.php
r3344738 r3416646 1 1 <?php 2 2 3 namespace PrashantWP\Email_Tracker\Admin\Email_List; 3 4 4 if ( ! defined( 'ABSPATH' ) ) {5 exit;5 if ( !defined( 'ABSPATH' ) ) { 6 exit; 6 7 } 7 8 9 8 use PrashantWP\Email_Tracker\Util; 10 11 9 class Setup extends \PrashantWP\Email_Tracker\Base { 12 13 10 private $menu_slug; 11 14 12 private $hook_suffix; 15 13 … … 21 19 public function init() { 22 20 $this->hook(); 23 24 21 $this->menu_page(); 25 22 $this->help_tabs(); … … 28 25 29 26 public function hook() { 30 add_action( 'init', array( $this, 'init_hook' ), 10 ); 31 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 999, 1 ); 32 33 if ( emtr()->is__premium_only() ) { 34 $option_name = $this->factory->get( 'PrashantWP\Email_Tracker\Options' )->get_option_name(); 35 add_action( 'add_option_' . $option_name , array( $this, 'set_up_capability_to_roles_add_hook__premium_only' ), 10, 2 ); 36 add_action( 'update_option_' . $option_name , array( $this, 'set_up_capability_to_roles_update_hook__premium_only' ), 10, 3 ); 37 add_action( 'init', function () { 38 if ( ! wp_next_scheduled( 'email_tracker_delete_emails_after_days' ) ) { 39 wp_schedule_event( time(), 'hourly', 'email_tracker_delete_emails_after_days', array(), false ); 40 } 41 add_action( 'email_tracker_delete_emails_after_days', array( $this, 'email_tracker_delete_emails_after_days__premium_only' ) ); 42 } ); 43 } 44 45 add_action( 'rest_api_init', array( $this, 'rest_api_init' ) ); 27 add_action( 'init', array($this, 'init_hook'), 10 ); 28 add_action( 29 'admin_enqueue_scripts', 30 array($this, 'admin_enqueue_scripts'), 31 999, 32 1 33 ); 34 add_action( 'rest_api_init', array($this, 'rest_api_init') ); 46 35 } 47 36 … … 55 44 56 45 public function menu_page() { 57 add_action( 'admin_menu', function () {58 $view_page = new Page_Viewer();59 $hook_suffix = add_menu_page(60 esc_html__( 'Email List', 'email-tracker' ),61 esc_html__( 'Email Tracker', 'email-tracker' ),62 $this->get_cap_to_manage_all_emails(),63 $this->get_menu_slug(),64 [ $view_page, 'view'],65 'dashicons-email-alt'66 );67 } );46 add_action( 'admin_menu', function () { 47 $view_page = new Page_Viewer(); 48 $hook_suffix = add_menu_page( 49 esc_html__( 'Email List', 'email-tracker' ), 50 esc_html__( 'Email Tracker', 'email-tracker' ), 51 $this->get_cap_to_manage_all_emails(), 52 $this->get_menu_slug(), 53 [$view_page, 'view'], 54 'dashicons-email-alt' 55 ); 56 } ); 68 57 } 69 58 … … 73 62 74 63 public function init_hook() { 75 if ( current_user_can( 'administrator' ) && ! current_user_can( $this->get_cap_to_manage_all_emails() )) {64 if ( current_user_can( 'administrator' ) && !current_user_can( $this->get_cap_to_manage_all_emails() ) ) { 76 65 $this->set_up_capability_to_administrator(); 77 66 } … … 82 71 } 83 72 84 public function set_up_capability_to_roles_add_hook__premium_only( $option, $value ) { 85 if ( ! current_user_can( 'manage_options' ) ) { 73 public function help_tabs() { 74 add_action( 'load-' . $this->get_hook_suffix(), function () { 75 $screen = get_current_screen(); 76 $screen->add_help_tab( [ 77 'id' => 'emtr_email_list_help_overview', 78 'title' => esc_html__( 'Overview', 'email-tracker' ), 79 'content' => '<p>' . esc_html__( 'This screen provides access to all of sent emails. You can see emails read log in Read Log column.', 'email-tracker' ) . '</p>', 80 ] ); 81 $screen->add_help_tab( [ 82 'id' => 'emtr_email_list_help_available_actions', 83 'title' => esc_html__( 'Available Actions', 'email-tracker' ), 84 'content' => '<p>' . esc_html__( 'Hovering over a row in the posts list will display action links that allow you to manage your post. You can perform the following actions:', 'email-tracker' ) . '</p>' . '<ul>' . '<li><strong>' . esc_html__( 'View', 'email-tracker' ) . '</strong> ' . __( 'will show you all email details.', 'email-tracker' ) . '</li>' . '<li><strong>' . esc_html__( 'Delete', 'email-tracker' ) . '</strong> ' . __( 'will permanently delete email.', 'email-tracker' ) . '</li>' . '<ul>', 85 ] ); 86 $screen->add_help_tab( [ 87 'id' => 'emtr_email_list_help_bulk_actions', 88 'title' => esc_html__( 'Bulk Actions', 'email-tracker' ), 89 'content' => '<p>' . esc_html__( 'You can also delete multiple emails at once. Select the emails you want to act on using the checkboxes, then select the action you want to take from the Bulk Actions menu and click Apply.', 'email-tracker' ) . '</p>', 90 ] ); 91 unset($screen); 92 } ); 93 } 94 95 public function help_options() { 96 add_action( 'load-' . $this->get_hook_suffix(), function () { 97 $screen = get_current_screen(); 98 add_screen_option( 'per_page', [ 99 'label' => esc_html__( 'Emails per page', 'email-tracker' ), 100 'default' => 50, 101 'option' => 'emtr_emails_per_page', 102 ] ); 103 unset($screen); 104 } ); 105 add_filter( 106 'set-screen-option', 107 function ( $status, $option, $value ) { 108 if ( 'emtr_emails_per_page' === $option ) { 109 return intval( $value ); 110 } else { 111 return $value; 112 } 113 }, 114 10, 115 3 116 ); 117 } 118 119 /** 120 * Enqueue notes scripts 121 */ 122 public function admin_enqueue_scripts( $hook_suffix ) { 123 // bail if email tracker admin page doesn't 124 if ( $this->get_hook_suffix() !== $hook_suffix ) { 86 125 return; 87 126 } 88 89 $option_name = $this->factory->get( 'PrashantWP\Email_Tracker\Options' )->get_option_name();90 if ( $option_name != $option ) {91 return;92 }93 94 $new_roles = isset( $value['roles_to_access_all_emails'] ) ? $value['roles_to_access_all_emails'] : array();95 if ( is_array( $new_roles ) && ! empty( $new_roles ) ) {96 foreach ( $new_roles as $new_role ) {97 wp_roles()->add_cap( $new_role, $this->get_cap_to_manage_all_emails(), true );98 }99 }100 }101 102 public function set_up_capability_to_roles_update_hook__premium_only( $old_option_values, $new_option_values, $option ) {103 if ( ! current_user_can( 'manage_options' ) ) {104 return;105 }106 107 $option_name = $this->factory->get( 'PrashantWP\Email_Tracker\Options' )->get_option_name();108 if ( $option_name != $option ) {109 return;110 }111 // error_log( 'update_option' );112 113 $old_roles = isset( $old_option_values['roles_to_access_all_emails'] ) ? $old_option_values['roles_to_access_all_emails'] : array();114 if ( is_array( $old_roles ) && ! empty( $old_roles ) ) {115 foreach ( $old_roles as $old_role ) {116 wp_roles()->remove_cap( $old_role, $this->get_cap_to_manage_all_emails() );117 }118 }119 120 $new_roles = isset( $new_option_values['roles_to_access_all_emails'] ) ? $new_option_values['roles_to_access_all_emails'] : array();121 if ( is_array( $new_roles ) && ! empty( $new_roles ) ) {122 foreach ( $new_roles as $new_role ) {123 wp_roles()->add_cap( $new_role, $this->get_cap_to_manage_all_emails(), true );124 }125 }126 }127 128 public function help_tabs() {129 130 add_action( 'load-' . $this->get_hook_suffix(), function () {131 $screen = get_current_screen();132 133 $screen->add_help_tab( [134 'id' => 'emtr_email_list_help_overview',135 'title' => esc_html__( 'Overview', 'email-tracker' ),136 'content' => '<p>' . esc_html__( 'This screen provides access to all of sent emails. You can see emails read log in Read Log column.', 'email-tracker' ) . '</p>',137 ] );138 139 $screen->add_help_tab( [140 'id' => 'emtr_email_list_help_available_actions',141 'title' => esc_html__('Available Actions', 'email-tracker' ),142 'content' => '<p>' . esc_html__( 'Hovering over a row in the posts list will display action links that allow you to manage your post. You can perform the following actions:', 'email-tracker' ) . '</p>' .143 '<ul>' .144 '<li><strong>' . esc_html__( 'View', 'email-tracker' ).'</strong> ' . __( 'will show you all email details.', 'email-tracker' ).'</li>' .145 '<li><strong>' . esc_html__( 'Delete', 'email-tracker' ).'</strong> ' . __( 'will permanently delete email.', 'email-tracker' ).'</li>' .146 '<ul>',147 ] );148 149 $screen->add_help_tab( [150 'id' => 'emtr_email_list_help_bulk_actions',151 'title' => esc_html__( 'Bulk Actions', 'email-tracker' ),152 'content' => '<p>' .153 esc_html__( 'You can also delete multiple emails at once. Select the emails you want to act on using the checkboxes, then select the action you want to take from the Bulk Actions menu and click Apply.', 'email-tracker' ) .154 '</p>',155 ] );156 157 unset( $screen );158 } );159 }160 161 public function help_options() {162 add_action( 'load-' . $this->get_hook_suffix(), function() {163 $screen = get_current_screen();164 add_screen_option( 'per_page', [165 'label' => esc_html__('Emails per page', 'email-tracker' ),166 'default' => 50,167 'option' => 'emtr_emails_per_page',168 ] );169 170 unset( $screen );171 } );172 add_filter( 'set-screen-option', function( $status, $option, $value ) {173 if ( 'emtr_emails_per_page' === $option ) {174 return intval( $value );175 } else {176 return $value;177 }178 }, 10, 3 );179 }180 181 /**182 * Enqueue notes scripts183 */184 public function admin_enqueue_scripts( $hook_suffix ) {185 // bail if email tracker admin page doesn't186 if ( $this->get_hook_suffix() !== $hook_suffix ) {187 return;188 }189 190 127 $asset_path = plugin_dir_path( EMTR_FILE ) . 'assets/build/'; 191 128 $asset_url = plugin_dir_url( EMTR_FILE ) . 'assets/build/'; 192 $asset_file = include $asset_path . 'index.asset.php'; 193 194 wp_enqueue_script( 195 'emtr-email-list', 196 $asset_url . 'index.js', 197 $asset_file['dependencies'], 198 $asset_file['version'], 199 true 200 ); 201 wp_localize_script( 202 'emtr-email-list', 203 'email_tracker', 204 array( 205 'content_url' => content_url(), 206 ) 207 ); 129 $asset_file = (include $asset_path . 'index.asset.php'); 130 wp_enqueue_script( 131 'emtr-email-list', 132 $asset_url . 'index.js', 133 $asset_file['dependencies'], 134 $asset_file['version'], 135 true 136 ); 137 wp_localize_script( 'emtr-email-list', 'email_tracker', array( 138 'content_url' => content_url(), 139 ) ); 208 140 wp_enqueue_style( 'wp-components' ); 209 210 141 if ( file_exists( $asset_path . 'index.css' ) ) { 211 142 wp_enqueue_style( … … 213 144 $asset_url . 'index.css', 214 145 array(), 215 ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? time() : '1.0.1',146 ( defined( 'WP_DEBUG' ) && WP_DEBUG ? time() : '1.0.1' ), 216 147 'all' 217 148 ); 218 149 } 150 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- the full plugin name is used in hook name. 219 151 do_action( 'email-tracker/admin_enqueue_scripts' ); 220 221 if ( emtr()->can_use_premium_code__premium_only() ) { 222 $pro_asset_path = $asset_path . 'pro/'; 223 $pro_asset_url = $asset_url . 'pro/'; 224 $asset_file = include $pro_asset_path . 'index.asset.php'; 225 226 wp_enqueue_script( 227 'emtr-email-list-pro', 228 $pro_asset_url . 'index.js', 229 array_merge(array('emtr-email-list'), $asset_file['dependencies']), 230 $asset_file['version'], 231 true 232 ); 233 234 if ( file_exists( $pro_asset_path . 'index.css' ) ) { 235 wp_enqueue_style( 236 'emtr-email-list-pro', 237 $pro_asset_url . 'index.css', 238 array(), 239 ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? time() : '1.0.1', 240 'all' 241 ); 242 } 243 } 244 } 245 246 public function email_tracker_delete_emails_after_days__premium_only() { 247 global $wpdb; 248 249 $delete_emails_after_days = $this->factory->get( '\PrashantWP\Email_Tracker\Options' )->get( 'delete_emails_after_days', 30 ); 250 if ( $delete_emails_after_days <= 0 ) { 251 return; 252 } 253 $now_gmt = strtotime( gmdate("Y-m-d H:i:s", time() ) ); 254 $days_ago_timestamp = $now_gmt - ( $delete_emails_after_days * 86400 ); 255 $days_ago_date_time = date( 'Y-m-d H:i:s', $days_ago_timestamp ); 256 $limit = defined('EMTR_DELETE_EMAILS_AFTER_DAYS_BATCH_SIZE') && is_numeric(EMTR_DELETE_EMAILS_AFTER_DAYS_BATCH_SIZE) ? (int) EMTR_DELETE_EMAILS_AFTER_DAYS_BATCH_SIZE : 250; 257 $sql = $wpdb->prepare( 'SELECT email_id FROM ' . Util::emtr_get_table_name( 'email' ) . ' WHERE date_time <= %s LIMIT '.$limit.';', $days_ago_date_time ); 258 $email_ids = $wpdb->get_col( $sql ); 259 260 if ( is_array( $email_ids ) && count( $email_ids ) > 0 ) { 261 Util::delete_emails( $email_ids ); 262 } 263 } 152 } 264 153 265 154 public function rest_api_init() { 266 155 // email-tracker/v1/email/5 267 register_rest_route( 268 'email-tracker/v1', 269 'email/(?P<id>[\d]+)', 270 array( 271 'methods' => 'GET', 272 'callback' => array( $this, 'get_email_for_view' ), 273 'args' => array( 274 'id' => array( 275 'validate_callback' => array( $this, 'rest_validate_email_id_request' ), 276 ), 156 register_rest_route( 'email-tracker/v1', 'email/(?P<id>[\\d]+)', array( 157 'methods' => 'GET', 158 'callback' => array($this, 'get_email_for_view'), 159 'args' => array( 160 'id' => array( 161 'validate_callback' => array($this, 'rest_validate_email_id_request'), 277 162 ), 278 'permission_callback' => array( $this, 'rest_permission_check'),279 )280 ) ;163 ), 164 'permission_callback' => array($this, 'rest_permission_check'), 165 ) ); 281 166 } 282 167 … … 291 176 public function get_email_for_view( $request ) { 292 177 global $wpdb; 293 294 178 $ret_data = array(); 295 179 $email_id = $request['id']; 296 297 $sql = $wpdb->prepare( 'SELECT `to`, subject, message, message_plain, headers, attachments, date_time, '. 298 '(SELECT count( trkemail_id ) FROM ' . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ) . ' WHERE trkemail_email_id = em.email_id) AS total_read_count, '. 299 '(SELECT count( trklinkclick_id ) FROM ' . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_click_log' ) . ' WHERE trklinkclick_email_id = em.email_id ) AS total_link_click_count '. 300 'FROM ' . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'email' ) . ' AS em WHERE email_id=%d', $email_id ); 180 $sql = $wpdb->prepare( 'SELECT `to`, subject, message, message_plain, headers, attachments, date_time, ' . '(SELECT count( trkemail_id ) FROM ' . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ) . ' WHERE trkemail_email_id = em.email_id) AS total_read_count, ' . '(SELECT count( trklinkclick_id ) FROM ' . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_click_log' ) . ' WHERE trklinkclick_email_id = em.email_id ) AS total_link_click_count ' . 'FROM ' . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'email' ) . ' AS em WHERE email_id=%d', $email_id ); 181 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.NotPrepared 301 182 $email_row = $wpdb->get_row( $sql, ARRAY_A ); 302 303 183 if ( is_null( $email_row ) ) { 304 throw new Exception( 'Email can\'t be found!');184 throw new Exception(esc_attr( 'Email can\'t be found!' )); 305 185 } 306 186 $pass_key_arr = array( … … 313 193 'date_time', 314 194 'total_read_count', 315 'total_link_click_count' ,316 ); 317 foreach ( $pass_key_arr as $field ) {195 'total_link_click_count' 196 ); 197 foreach ( $pass_key_arr as $field ) { 318 198 $ret_data[$field] = $email_row[$field]; 319 199 } 320 321 // For Duplicator like plugin send full path in scheduled package 322 323 if ( ! empty( $ret_data['attachments'] ) ) { 324 $attachments_sep = ',\n'; 325 $attachments = array_map( 'trim', explode( $attachments_sep, $ret_data['attachments'] ) ); 326 $new_attachments_arr = array(); 327 $home_path_len = strlen( WP_CONTENT_DIR ); 328 329 $upload_dir = wp_upload_dir(); 330 foreach ( $attachments as $attachment ) { 331 if ( 0 === stripos( $attachment, WP_CONTENT_DIR ) && 0 !== stripos( $attachment, $upload_dir['basedir'] ) ) { 332 $new_attachments_arr[] = substr( $attachment, $home_path_len ); 333 } else { 334 $new_attachments_arr[] = $attachment; 335 } 336 } 337 $ret_data['attachments'] = implode( $attachments_sep, $new_attachments_arr ); 338 } 339 340 341 /* 342 echo '<pre>'; 343 print_r(WP_CONTENT_DIR); 344 echo '</pre>'; 345 */ 346 // die; 347 /* 348 echo '<pre>'; 349 print_r($ret_data['attachments']); 350 echo '</pre>'; 351 die; 352 */ 353 354 200 // For Duplicator like plugin send full path in scheduled package 201 if ( !empty( $ret_data['attachments'] ) ) { 202 $attachments_sep = ',\\n'; 203 $attachments = array_map( 'trim', explode( $attachments_sep, $ret_data['attachments'] ) ); 204 $new_attachments_arr = array(); 205 $home_path_len = strlen( WP_CONTENT_DIR ); 206 $upload_dir = wp_upload_dir(); 207 foreach ( $attachments as $attachment ) { 208 if ( 0 === stripos( $attachment, WP_CONTENT_DIR ) && 0 !== stripos( $attachment, $upload_dir['basedir'] ) ) { 209 $new_attachments_arr[] = substr( $attachment, $home_path_len ); 210 } else { 211 $new_attachments_arr[] = $attachment; 212 } 213 } 214 $ret_data['attachments'] = implode( $attachments_sep, $new_attachments_arr ); 215 } 355 216 $ret_data['read_log'] = array(); 356 $sql = $wpdb->prepare( 'SELECT trkemail_id as read_id, trkemail_date_time as date_time, trkemail_ip_address as ip_address FROM ' . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ) . ' EOD WHERE EOD.trkemail_email_id = %d ORDER BY EOD.trkemail_date_time DESC', $email_id );357 $email_open_res = $wpdb->get_results( $ sql, ARRAY_A );217 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 218 $email_open_res = $wpdb->get_results( $wpdb->prepare( "SELECT trkemail_id as read_id, trkemail_date_time as date_time, trkemail_ip_address as ip_address FROM " . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ) . " EOD WHERE EOD.trkemail_email_id = %d ORDER BY EOD.trkemail_date_time DESC", $email_id ), ARRAY_A ); 358 219 foreach ( $email_open_res as $row ) { 359 220 $ret_data['read_log'][] = array( 360 'read_id' => $row['read_id'],361 'date_time' => $row['date_time'],221 'read_id' => $row['read_id'], 222 'date_time' => $row['date_time'], 362 223 'ip_address' => $row['ip_address'], 363 224 ); 364 225 } 365 366 226 $ret_data['link_click_log'] = array(); 367 $email_link_res = 'SELECT trkemail_date_time as date_time, trkemail_ip_address as ip_address FROM ' . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_open_log' ) . ' EOD WHERE EOD.trkemail_email_id = E.email_id ORDER BY EOD.trkemail_date_time DESC'; 368 369 $sql = $GLOBALS['wpdb']->prepare( 370 'SELECT lm.trklink_id as link_id, lm.trklink_link as link, lc.trklinkclick_date_time as date_time, lc.trklinkclick_ip_address as ip_address '. 371 'FROM ' . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_master' ) . ' lm LEFT JOIN ' . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_click_log' ) . ' lc '. 372 ' ON lm.trklink_id = lc.trklinkclick_trklink_id '. 373 'WHERE lm.trklink_email_id = %d '. 374 'ORDER BY lm.trklink_id ASC, lc.trklinkclick_date_time DESC;', 375 $email_id 376 ); 377 $email_link_res = $GLOBALS['wpdb']->get_results( $sql, ARRAY_A ); 378 227 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 228 $email_link_res = $wpdb->get_results( $wpdb->prepare( "SELECT lm.trklink_id as link_id, lm.trklink_link as link, lc.trklinkclick_date_time as date_time, lc.trklinkclick_ip_address as ip_address " . "FROM " . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_master' ) . " lm LEFT JOIN " . \PrashantWP\Email_Tracker\Util::emtr_get_table_name( 'track_email_link_click_log' ) . " lc " . " ON lm.trklink_id = lc.trklinkclick_trklink_id " . "WHERE lm.trklink_email_id = %d " . "ORDER BY lm.trklink_id ASC, lc.trklinkclick_date_time DESC;", $email_id ), ARRAY_A ); 379 229 foreach ( $email_link_res as $row ) { 380 230 $ret_data['link_click_log'][] = array( 381 'link_id' => $row['link_id'],382 'link' => $row['link'],383 'date_time' => $row['date_time'],231 'link_id' => $row['link_id'], 232 'link' => $row['link'], 233 'date_time' => $row['date_time'], 384 234 'ip_address' => $row['ip_address'], 385 235 ); 386 236 } 387 388 237 return $ret_data; 389 238 } -
email-tracker/trunk/src/admin/email-list/class-table.php
r3344738 r3416646 1 1 <?php 2 2 3 /** 3 4 * To list of all emails 4 5 */ 5 6 namespace PrashantWP\Email_Tracker\Admin\Email_List; 6 7 if ( ! defined( 'ABSPATH' ) ) {8 exit;7 8 if ( !defined( 'ABSPATH' ) ) { 9 exit; 9 10 } 10 11 11 use PrashantWP\Email_Tracker\Util; 12 13 if ( ! class_exists('\WP_List_Table' ) ) { 14 require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' ); 12 if ( !class_exists( '\\WP_List_Table' ) ) { 13 require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; 15 14 } 16 17 15 /************************** CREATE A PACKAGE CLASS ***************************** 18 16 ******************************************************************************* … … 29 27 */ 30 28 class Table extends \WP_List_Table { 31 32 33 protected $table_name; 34 protected $open_log_table_name; 35 protected $key = 'email_id'; 36 protected $key_field = 'to'; 37 38 protected $content_path; 29 protected $table_name; 30 31 protected $open_log_table_name; 32 33 protected $key = 'email_id'; 34 35 protected $key_field = 'to'; 36 37 protected $content_path; 39 38 40 39 /** ************************************************************************ … … 42 41 * use the parent reference to set some default configs. 43 42 ***************************************************************************/ 44 function __construct() {43 function __construct() { 45 44 global $status, $page; 46 global $wpdb; 47 48 $this->table_name = Util::emtr_get_table_name( 'email' ); 49 $this->open_log_table_name = Util::emtr_get_table_name( 'track_email_open_log' ); 50 51 $this->content_path = WP_CONTENT_URL; 52 45 global $wpdb; 46 $this->table_name = Util::emtr_get_table_name( 'email' ); 47 $this->open_log_table_name = Util::emtr_get_table_name( 'track_email_open_log' ); 48 $this->content_path = WP_CONTENT_URL; 53 49 //Set parent defaults 54 50 parent::__construct( array( 55 'singular' => __('email', 'email-tracker'), //singular name of the listed records56 'plural' => __('emails', 'email-tracker'), //plural name of the listed records57 'ajax' => false //does this table support ajax?51 'singular' => __( 'email', 'email-tracker' ), 52 'plural' => __( 'emails', 'email-tracker' ), 53 'ajax' => false, 58 54 ) ); 59 60 55 } 61 56 62 57 private function get_view_link( $item, $link_label ) { 63 return '<a href="#" onClick="return EMTRLoadView( ' . esc_js( $item[$this->key] ) . ', \'' . esc_js( $item['subject'] ) . '\', \'' . esc_js( $item[$this->key_field] ) . '\')">' . esc_html( $link_label ) . '</a>';58 return '<a href="#" onClick="return EMTRLoadView( ' . esc_js( $item[$this->key] ) . ', \'' . esc_js( $item['subject'] ) . '\', \'' . esc_js( $item[$this->key_field] ) . '\')">' . esc_html( $link_label ) . '</a>'; 64 59 } 65 60 … … 85 80 * @return string Text or HTML to be placed inside the column <td> 86 81 **************************************************************************/ 87 function column_default( $item, $column_name){88 switch ($column_name){82 function column_default( $item, $column_name ) { 83 switch ( $column_name ) { 89 84 case 'subject': 90 return self::get_view_link( $item, $item['subject'] ); 91 case 'view_count': 92 /* translators: %s: Number of times email was read */ 93 $str = '<b>'.sprintf( _n( '%s time', '%s times', $item[$column_name], 'email-tracker' ), $item[$column_name] ) . __( ' read', 'email-tracker' ) . '</b>'; 94 if( $item[$column_name] == 0 ) { 95 $str .= '<div alt="f147" class="dashicons dashicons-no-alt"></div>'; 96 } 97 else { 98 $str .= '<div alt="f147" class="dashicons dashicons-yes"></div>'; 99 } 100 $str .= '<br/>'; 101 if( !empty($item['view_date_time']) ) { 102 $arr_view_date_time = explode(',', $item['view_date_time']); 103 rsort( $arr_view_date_time ); 104 $str .= __( 'Last read on ', 'email-tracker' ). get_date_from_gmt( $arr_view_date_time[0], 'F j, Y g:i A' ).' ' . Util::emtr_relative_time(get_date_from_gmt( $arr_view_date_time[0] ) ); 105 106 } 107 return $str; 108 109 110 case 'click_count': 111 if ( emtr()->is__premium_only() ) { 112 if ( emtr()->is_plan( 'pro', true ) || emtr()->is_trial() ) { 113 /* translators: %s: Number of times link was clicked */ 114 $str = '<b>'.sprintf( _n( '%s time', '%s times', $item[$column_name], 'email-tracker' ), $item[$column_name] ).__(' clicked', 'email-tracker').'</b>'; 115 if( $item[$column_name] == 0 ) { 116 $str .= '<div alt="f147" class="dashicons dashicons-no-alt"></div>'; 117 } 118 else { 119 $str .= '<div alt="f147" class="dashicons dashicons-yes"></div>'; 120 } 121 $str .= '<br/>'; 122 if( !empty($item['click_date_time']) ) { 123 $arr_click_date_time = explode(',',$item['click_date_time']); 124 rsort( $arr_click_date_time ); 125 $str .= __('Last click on ', 'email-tracker'). get_date_from_gmt($arr_click_date_time[0], 'F j, Y g:i A').' '.Util::emtr_relative_time(get_date_from_gmt( $arr_click_date_time[0] )); 126 127 } 128 return $str; 129 } 130 } 131 /* translators: %1$s: Opening link tag, %2$s: Closing link tag */ 132 return '<strong>' . sprintf( __( 'To Track Email Links, Please %1$sUpgrade Now!%2$s', 'email-tracker'), '<a href="' . emtr()->get_upgrade_url() . '">', '</a>' ) . '<strong>'; 85 return self::get_view_link( $item, $item['subject'] ); 86 case 'view_count': 87 /* translators: %s: Number of times email was read */ 88 $str = '<b>' . sprintf( _n( 89 '%s time', 90 '%s times', 91 $item[$column_name], 92 'email-tracker' 93 ), $item[$column_name] ) . __( ' read', 'email-tracker' ) . '</b>'; 94 if ( $item[$column_name] == 0 ) { 95 $str .= '<div alt="f147" class="dashicons dashicons-no-alt"></div>'; 96 } else { 97 $str .= '<div alt="f147" class="dashicons dashicons-yes"></div>'; 98 } 99 $str .= '<br/>'; 100 if ( !empty( $item['view_date_time'] ) ) { 101 $arr_view_date_time = explode( ',', $item['view_date_time'] ); 102 rsort( $arr_view_date_time ); 103 $str .= __( 'Last read on ', 'email-tracker' ) . get_date_from_gmt( $arr_view_date_time[0], 'F j, Y g:i A' ) . ' ' . Util::emtr_relative_time( get_date_from_gmt( $arr_view_date_time[0] ) ); 104 } 105 return $str; 106 case 'click_count': 107 /* translators: %1$s: Opening link tag, %2$s: Closing link tag */ 108 return '<strong>' . sprintf( __( 'To Track Email Links, Please %1$sUpgrade Now!%2$s', 'email-tracker' ), '<a href="' . emtr()->get_upgrade_url() . '">', '</a>' ) . '<strong>'; 133 109 case 'date_time': 134 return get_date_from_gmt( $item[$column_name] ,'F j, Y g:i A' ) . Util::emtr_relative_time( get_date_from_gmt( $item[$column_name] ) ); 135 136 case 'headers': 137 return nl2br( $item[$column_name] ); 138 case 'attachments': 139 if( empty($item[$column_name]) ) 140 return $item[$column_name]; 141 $arr_attachments = explode( ',\n', $item[$column_name] ); 142 $str_attach = ''; 143 foreach( $arr_attachments as $key=>$attach ) { 144 $str_attach .= '<a href="'. esc_url( $this->content_path.$attach ).'" title="'. esc_attr( $this->content_path . $attach ) .'" alt="'. esc_attr( $this->content_path . $attach ) .'" class="dashicons dashicons-paperclip" target="_blank">'.'</a>'; 145 if( $key != count($arr_attachments) - 1 ) { 146 //$str_attach .= ',<br/>'; 147 } 148 } 149 return $str_attach; 150 151 default: 152 return print_r($item,true); //Show the whole array for troubleshooting purposes 153 } 154 } 155 110 return get_date_from_gmt( $item[$column_name], 'F j, Y g:i A' ) . Util::emtr_relative_time( get_date_from_gmt( $item[$column_name] ) ); 111 case 'headers': 112 return nl2br( $item[$column_name] ); 113 case 'attachments': 114 if ( empty( $item[$column_name] ) ) { 115 return $item[$column_name]; 116 } 117 $arr_attachments = explode( ',\\n', $item[$column_name] ); 118 $str_attach = ''; 119 foreach ( $arr_attachments as $key => $attach ) { 120 $str_attach .= '<a href="' . esc_url( $this->content_path . $attach ) . '" title="' . esc_attr( $this->content_path . $attach ) . '" alt="' . esc_attr( $this->content_path . $attach ) . '" class="dashicons dashicons-paperclip" target="_blank">' . '</a>'; 121 if ( $key != count( $arr_attachments ) - 1 ) { 122 //$str_attach .= ',<br/>'; 123 } 124 } 125 return $str_attach; 126 } 127 } 156 128 157 129 /** ************************************************************************ … … 171 143 * @return string Text to be placed inside the column <td> (movie title only) 172 144 **************************************************************************/ 173 function column_to( $item){174 $delete_url = wp_nonce_url( sprintf( '?page=emtr_email_list&action=%s&email=%s', 'delete', intval( $item[$this->key] ) ), 'emtr-email-list-delete-' .$item[$this->key], '_wpnonce' );145 function column_to( $item ) { 146 $delete_url = wp_nonce_url( sprintf( '?page=emtr_email_list&action=%s&email=%s', 'delete', intval( $item[$this->key] ) ), 'emtr-email-list-delete-' . $item[$this->key], '_wpnonce' ); 175 147 $actions = array( 176 'edit' => self::get_view_link( $item, __( 'View', 'email-tracker' ) ),177 'delete' => '<a href="' . $delete_url . '" class="delete">Delete</a>',148 'edit' => self::get_view_link( $item, __( 'View', 'email-tracker' ) ), 149 'delete' => '<a href="' . $delete_url . '" class="delete">Delete</a>', 178 150 ); 179 180 151 //Return the title contents 181 return sprintf('%1$s <span style="color:silver">(id:%2$s)</span>%3$s', 182 /*$1%s*/ $item[$this->key_field], 183 /*$2%s*/ $item[$this->key], 184 /*$3%s*/ $this->row_actions($actions) 152 return sprintf( 153 '%1$s <span style="color:silver">(id:%2$s)</span>%3$s', 154 /*$1%s*/ 155 $item[$this->key_field], 156 /*$2%s*/ 157 $item[$this->key], 158 /*$3%s*/ 159 $this->row_actions( $actions ) 185 160 ); 186 161 } 187 188 162 189 163 /** ************************************************************************ … … 196 170 * @return string Text to be placed inside the column <td> (movie title only) 197 171 **************************************************************************/ 198 function column_cb( $item){199 return sprintf( 172 function column_cb( $item ) { 173 return sprintf( 200 174 '<input type="checkbox" name="%1$s[]" value="%2$s" />', 201 /*$1%s*/ $this->_args['singular'], //Let's simply repurposed the table's singular label ("movie") 202 /*$2%s*/ $item[$this->key] //The value of the checkbox should be the record's id 203 ); 204 } 205 175 /*$1%s*/ 176 $this->_args['singular'], 177 //Let's simply repurposed the table's singular label ("movie") 178 /*$2%s*/ 179 $item[$this->key] 180 ); 181 } 206 182 207 183 /** ************************************************************************ … … 218 194 * @return array An associative array containing column information: 'slugs'=>'Visible Titles' 219 195 **************************************************************************/ 220 function get_columns() {196 function get_columns() { 221 197 $columns = array( 222 'cb' => '<input type="checkbox" />', //Render a checkbox instead of text198 'cb' => '<input type="checkbox" />', 223 199 'to' => esc_html__( 'To', 'email-tracker' ), 224 200 'subject' => esc_html__( 'Subject', 'email-tracker' ), 225 'date_time' => esc_html__( 'Date', 'email-tracker' ), 226 'view_count' => esc_html__( 'Read Log', 'email-tracker' ), 227 'click_count' => esc_html__( 'Click Log', 'email-tracker' ), 228 229 //'headers' => 'Headers', 230 //'attachments' => 'Attachments' 201 'date_time' => esc_html__( 'Date', 'email-tracker' ), 202 'view_count' => esc_html__( 'Read Log', 'email-tracker' ), 203 'click_count' => esc_html__( 'Click Log', 'email-tracker' ), 231 204 ); 232 205 return $columns; 233 206 } 234 235 207 236 208 /** ************************************************************************ … … 250 222 function get_sortable_columns() { 251 223 $sortable_columns = array( 252 'to' => array('to',false), //true means it's already sorted253 'subject' => array('subject',false),254 'date_time' => array('date_time',true),255 'view_count' => array('view_count',false),256 'click_count' => array('click_count',false) 224 'to' => array('to', false), 225 'subject' => array('subject', false), 226 'date_time' => array('date_time', true), 227 'view_count' => array('view_count', false), 228 'click_count' => array('click_count', false), 257 229 ); 258 230 return $sortable_columns; 259 231 } 260 261 232 262 233 /** ************************************************************************ … … 276 247 function get_bulk_actions() { 277 248 $actions = array( 278 'delete' => esc_html__( 'Delete', 'email-tracker' ),249 'delete' => esc_html__( 'Delete', 'email-tracker' ), 279 250 ); 280 251 return $actions; 281 252 } 282 283 253 284 254 /** ************************************************************************ … … 292 262 //Detect when a bulk action is being triggered... 293 263 if ( 'delete' === $this->current_action() ) { 294 // Bulk Delete264 // Bulk Delete 295 265 if ( isset( $_GET['action2'] ) && 'delete' == $_GET['action2'] ) { 296 if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'emtr-email-list-filter') ) { 297 die( 'Security issue1' ); 298 } 299 } else { // Single Email Delete action 300 $email_id = intval( $_GET['email'] ); 301 if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'emtr-email-list-delete-' . $email_id ) ) { 302 die( 'Security issue2' ); 303 } 304 } 305 306 global $wpdb; 307 266 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- No need of validation and unslash because of nonce verification logic. 267 if ( !wp_verify_nonce( $_REQUEST['_wpnonce'], 'emtr-email-list-filter' ) ) { 268 die( 'Security issue!' ); 269 } 270 } else { 271 // Single Email Delete action 272 //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- type casted to int. 273 $email_id = intval( $_GET['email'] ); 274 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- No need of validation and unslash because of nonce verification logic. 275 if ( !wp_verify_nonce( $_REQUEST['_wpnonce'], 'emtr-email-list-delete-' . $email_id ) ) { 276 die( 'Security issue!!' ); 277 } 278 } 279 global $wpdb; 308 280 if ( is_array( $_GET['email'] ) ) { 309 $arr_email_id = array_map( 'sanitize_text_field', $_GET['email'] ); 281 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated 282 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 283 $arr_email_id = array_map( 'sanitize_text_field', wp_unslash( $_GET['email'] ) ); 310 284 } else { 311 $arr_email_id = (array) sanitize_text_field( $_GET['email'] ); 312 }313 285 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.InputNotValidated 286 $arr_email_id = (array) sanitize_text_field( wp_unslash( $_GET['email'] ) ); 287 } 314 288 $arr_email_id = array_map( 'intval', $arr_email_id ); 315 $arr_email_id = array_filter( $arr_email_id ); 316 $arr_email_id = array_map( 'absint', $arr_email_id ); 317 if ( count( $arr_email_id ) > 0 ) { 318 Util::delete_emails( $arr_email_id ); 319 320 if ( count($arr_email_id) == 1 ) { 321 Util::emtr_set_success_msg( __( 'Email has been deleted successfully.', 'email-tracker' ) ); 322 } else { 323 Util::emtr_set_success_msg( __( 'Emails have been deleted successfully.', 'email-tracker' ) ); 324 } 325 } else { 326 Util::emtr_set_error_msg( __( 'Please select at least one email to delete.', 'email-tracker' ) ); 327 } 328 329 if ( wp_get_referer() ) { 330 wp_safe_redirect( wp_get_referer() ); 331 exit; 332 } 333 334 //wp_die('Items deleted (or they would be if we had items to delete)!'); 335 } 336 289 $arr_email_id = array_filter( $arr_email_id ); 290 $arr_email_id = array_map( 'absint', $arr_email_id ); 291 if ( count( $arr_email_id ) > 0 ) { 292 Util::delete_emails( $arr_email_id ); 293 if ( count( $arr_email_id ) == 1 ) { 294 Util::emtr_set_success_msg( __( 'Email has been deleted successfully.', 'email-tracker' ) ); 295 } else { 296 Util::emtr_set_success_msg( __( 'Emails have been deleted successfully.', 'email-tracker' ) ); 297 } 298 } else { 299 Util::emtr_set_error_msg( __( 'Please select at least one email to delete.', 'email-tracker' ) ); 300 } 301 if ( wp_get_referer() ) { 302 wp_safe_redirect( wp_get_referer() ); 303 exit; 304 } 305 } 337 306 } 338 307 … … 353 322 **************************************************************************/ 354 323 function prepare_items() { 355 global $wpdb; //This is used only if making any database queries356 324 global $wpdb; 325 //This is used only if making any database queries 357 326 /** 358 327 * First, lets decide how many records per page to show 359 328 */ 360 // get the current user ID 361 $user = get_current_user_id(); 362 // get the current admin screen 363 $screen = get_current_screen(); 364 365 // retrieve the "per_page" option 366 $screen_option = $screen->get_option( 'per_page', 'option' ); 367 368 // retrieve the value of the option stored for the current user 369 $per_page = get_user_meta( $user, $screen_option, true ); 370 if ( empty ( $per_page) || $per_page < 1 || is_array( $per_page ) ) { 371 // get the default value if none is set 372 $per_page = 50; 373 } 374 329 // get the current user ID 330 $user = get_current_user_id(); 331 // get the current admin screen 332 $screen = get_current_screen(); 333 // retrieve the "per_page" option 334 $screen_option = $screen->get_option( 'per_page', 'option' ); 335 // retrieve the value of the option stored for the current user 336 $per_page = get_user_meta( $user, $screen_option, true ); 337 if ( empty( $per_page ) || $per_page < 1 || is_array( $per_page ) ) { 338 // get the default value if none is set 339 $per_page = 50; 340 } 375 341 /** 376 342 * REQUIRED. Now we need to define our column headers. This includes a complete … … 383 349 $hidden = array(); 384 350 $sortable = $this->get_sortable_columns(); 385 386 387 351 /** 388 352 * REQUIRED. Finally, we build an array to be used by the class for column … … 392 356 */ 393 357 $this->_column_headers = array($columns, $hidden, $sortable); 394 395 396 358 /** 397 359 * Optional. You can handle your bulk actions however you see fit. In this … … 399 361 */ 400 362 $this->process_bulk_action(); 401 402 403 363 /** 404 364 * Instead of querying a database, we're going to fetch the example data … … 410 370 * be able to use your precisely-queried data immediately. 411 371 */ 412 413 414 415 372 /** 416 373 * This checks for sorting input and sorts the data in our array accordingly. … … 421 378 * sorting technique would be unnecessary. 422 379 */ 423 $orderby = ( ! empty( $_REQUEST['orderby'] ) ) ? sanitize_text_field( $_REQUEST['orderby'] ) : 'date_time'; //If no sort, default to title 424 if( $orderby == 'view_count' || $orderby == 'click_count') { 425 $orderby = $orderby ; 426 } 427 else { 428 $orderby = 'E.'.$orderby ; 429 } 430 380 $orderby = ( !empty( $_REQUEST['orderby'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ) : 'date_time' ); 381 // If no sort, default to title 382 if ( $orderby == 'view_count' || $orderby == 'click_count' ) { 383 $orderby = $orderby; 384 } elseif ( in_array( $orderby, array('to', 'subject', 'date_time'), true ) ) { 385 $orderby = 'E.' . $orderby; 386 } else { 387 $orderby = 'E.date_time'; 388 } 431 389 $order = 'DESC'; 432 if ( ! empty( $_REQUEST['order'] ) ) {433 $order_input = sanitize_text_field( $_REQUEST['order']);434 if ( ! in_array( $order_input, array( 'ASC', 'DESC') ) ) {390 if ( !empty( $_REQUEST['order'] ) ) { 391 $order_input = sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ); 392 if ( !in_array( $order_input, array('ASC', 'DESC') ) ) { 435 393 $order = $order_input; 436 394 } 437 395 } 438 439 396 /*********************************************************************** 440 397 * --------------------------------------------------------------------- … … 448 405 * --------------------------------------------------------------------- 449 406 **********************************************************************/ 450 451 407 /** 452 408 * REQUIRED for pagination. Let's figure out what page the user is currently … … 455 411 */ 456 412 $current_page = $this->get_pagenum(); 457 458 $wh = ' '; 459 460 //For search 461 if( isset( $_REQUEST['s'] ) && ! empty( $_REQUEST['s'] ) ) { 462 if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'emtr-email-list-filter' ) ) { 413 $wh = ' '; 414 //For search 415 if ( isset( $_REQUEST['s'] ) && !empty( $_REQUEST['s'] ) ) { 416 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- No need of validation and unslash because of nonce verification logic. 417 if ( !wp_verify_nonce( $_REQUEST['_wpnonce'], 'emtr-email-list-filter' ) ) { 463 418 die( 'Security issue' ); 464 419 } 465 466 $search_text = sanitize_text_field( $_REQUEST['s'] ); 467 468 $wh_arr = array(); 469 $arr_search_field = array( 'to', 'subject', 'message_plain', 'headers', 'attachments' ); 470 foreach ( $arr_search_field as $field ) { 471 $wh_arr[] = $wpdb->prepare( ' E.' . $field . ' LIKE %s', '%' . $wpdb->esc_like( $search_text ) . '%' ); 472 } 473 $wh = ' AND (' . implode( ' OR ' , $wh_arr). ')'; 474 } 475 476 420 $search_text = sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ); 421 $wh_arr = array(); 422 $arr_search_field = array( 423 'to', 424 'subject', 425 'message_plain', 426 'headers', 427 'attachments' 428 ); 429 foreach ( $arr_search_field as $field ) { 430 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared 431 $wh_arr[] = $wpdb->prepare( ' E.' . $field . ' LIKE %s', '%' . $wpdb->esc_like( $search_text ) . '%' ); 432 } 433 $wh = ' AND (' . implode( ' OR ', $wh_arr ) . ')'; 434 } 477 435 /** 478 436 * REQUIRED for pagination. Let's check how many items are in our data array. … … 481 439 * in your own package classes. 482 440 */ 483 //$total_items = count($data); 484 $total_items = $wpdb->get_var( 'SELECT count(*) FROM '.$this->table_name.' E WHERE 1 ' . $wh ); 485 486 441 //$total_items = count($data); 442 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 443 $total_items = $wpdb->get_var( 'SELECT count(*) FROM ' . $this->table_name . ' E WHERE 1 ' . $wh ); 487 444 /** 488 445 * The WP_List_Table class does not handle pagination for us, so we need … … 491 448 */ 492 449 //$data = array_slice($data,(($current_page-1)*$per_page),$per_page); 493 494 495 496 450 /** 497 451 * REQUIRED. Now we can add our *sorted* data to the items property, where … … 499 453 */ 500 454 $sql = 'SELECT E.*, 501 ( SELECT count(*) FROM '.$this->open_log_table_name. 502 ' EOC WHERE EOC.trkemail_email_id = E.email_id) AS view_count, 503 ( SELECT GROUP_CONCAT( trkemail_date_time ) FROM '.$this->open_log_table_name . 504 ' EOD WHERE EOD.trkemail_email_id = E.email_id ORDER BY EOD.trkemail_date_time DESC) AS view_date_time, 505 ( SELECT count(*) FROM ' . Util::emtr_get_table_name( 'track_email_link_click_log' ) . 506 ' ECL WHERE ECL.trklinkclick_email_id = E.email_id) AS click_count, 507 ( SELECT GROUP_CONCAT( trklinkclick_date_time ) FROM ' . Util::emtr_get_table_name( 'track_email_link_click_log' ) . ' ECLT WHERE ECLT.trklinkclick_email_id = E.email_id ORDER BY ECLT.trklinkclick_date_time DESC) AS click_date_time 508 FROM '.$this->table_name.' E WHERE 1 '.$wh.'ORDER BY '.$orderby.' '.$order.' LIMIT '.$per_page.' OFFSET '.(($current_page-1)*$per_page); 509 510 $this->items = $wpdb->get_results( $sql, ARRAY_A); 511 455 ( SELECT count(*) FROM ' . $this->open_log_table_name . ' EOC WHERE EOC.trkemail_email_id = E.email_id) AS view_count, 456 ( SELECT GROUP_CONCAT( trkemail_date_time ) FROM ' . $this->open_log_table_name . ' EOD WHERE EOD.trkemail_email_id = E.email_id ORDER BY EOD.trkemail_date_time DESC) AS view_date_time, 457 ( SELECT count(*) FROM ' . Util::emtr_get_table_name( 'track_email_link_click_log' ) . ' ECL WHERE ECL.trklinkclick_email_id = E.email_id) AS click_count, 458 ( SELECT GROUP_CONCAT( trklinkclick_date_time ) FROM ' . Util::emtr_get_table_name( 'track_email_link_click_log' ) . ' ECLT WHERE ECLT.trklinkclick_email_id = E.email_id ORDER BY ECLT.trklinkclick_date_time DESC) AS click_date_time 459 FROM ' . $this->table_name . ' E WHERE 1 ' . $wh . 'ORDER BY ' . $orderby . ' ' . $order . ' LIMIT ' . $per_page . ' OFFSET ' . ($current_page - 1) * $per_page; 460 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 461 $this->items = $wpdb->get_results( $sql, ARRAY_A ); 512 462 /** 513 463 * REQUIRED. We also have to register our pagination options & calculations. 514 464 */ 515 465 $this->set_pagination_args( array( 516 'total_items' => $total_items, //WE have to calculate the total number of items517 'per_page' => $per_page, //WE have to determine how many items to show on a page518 'total_pages' => ceil( $total_items / $per_page ) //WE have to calculate the total number of pages466 'total_items' => $total_items, 467 'per_page' => $per_page, 468 'total_pages' => ceil( $total_items / $per_page ), 519 469 ) ); 520 470 } 471 521 472 } -
email-tracker/trunk/src/class-util.php
r3340406 r3416646 115 115 116 116 // Delete from email table 117 // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 117 118 $wpdb->query( 118 119 $wpdb->prepare( 120 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared 119 121 "DELETE FROM " . self::emtr_get_table_name( 'email' ) . " WHERE email_id IN ($placeholders)", 120 122 $email_ids … … 123 125 124 126 // Delete from track_email_open_log table 127 // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 125 128 $wpdb->query( 126 129 $wpdb->prepare( 127 "DELETE FROM " . self::emtr_get_table_name( 'track_email_open_log' ) . " WHERE trkemail_email_id IN ($placeholders)", 130 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 131 "DELETE FROM ". self::emtr_get_table_name( 'track_email_open_log' ) . " WHERE trkemail_email_id IN ($placeholders)", 128 132 $email_ids 129 133 ) … … 131 135 132 136 // Delete from track_email_link_click_log table 137 // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 133 138 $wpdb->query( 134 139 $wpdb->prepare( 135 "DELETE FROM " . self::emtr_get_table_name( 'track_email_link_click_log' ) . 136 " WHERE trklinkclick_trklink_id IN (SELECT trklink_id FROM " . self::emtr_get_table_name( 'track_email_link_master' ) . 137 " WHERE trklink_email_id IN ($placeholders))", 140 "DELETE FROM " . self::emtr_get_table_name( 'track_email_link_click_log' ) . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared 141 " WHERE trklinkclick_trklink_id IN (SELECT trklink_id FROM " . self::emtr_get_table_name( 'track_email_link_master' ) . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared 142 " WHERE trklink_email_id IN ($placeholders))", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare 138 143 $email_ids 139 144 ) … … 141 146 142 147 // Delete from track_email_link_master table 148 // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 143 149 $wpdb->query( 144 150 $wpdb->prepare( 151 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare 145 152 "DELETE FROM " . self::emtr_get_table_name( 'track_email_link_master' ) . " WHERE trklink_email_id IN ($placeholders)", 146 153 $email_ids -
email-tracker/trunk/src/core/class-chunk-processor.php
r3344738 r3416646 159 159 160 160 $days_old = isset( $progress['data']['days_old'] ) ? $progress['data']['days_old'] : 30; 161 $date_threshold = date( 'Y-m-d H:i:s', strtotime( "-{$days_old} days" ) );161 $date_threshold = gmdate( 'Y-m-d H:i:s', strtotime( "-{$days_old} days" ) ); 162 162 163 163 $table_name = $wpdb->prefix . 'emtr_email_logs'; 164 164 165 165 // Get emails to delete 166 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 166 167 $emails = $wpdb->get_results( 167 $wpdb->prepare( 168 "SELECT id FROM {$table_name} 169 WHERE created_at < %s 170 LIMIT %d OFFSET %d", 168 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table_name is safe var val. 169 $wpdb->prepare("SELECT id FROM {$table_name} WHERE created_at < %s LIMIT %d OFFSET %d", // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 171 170 $date_threshold, 172 171 $chunk_size, … … 183 182 184 183 // Delete related data 184 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 185 185 $wpdb->query( 186 186 $wpdb->prepare( 187 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare 187 188 "DELETE FROM {$wpdb->prefix}emtr_email_open_logs WHERE email_id IN ($placeholders)", 188 189 $email_ids 189 190 ) 190 191 ); 191 192 $wpdb->query( 193 $wpdb->prepare( 194 "DELETE FROM {$wpdb->prefix}emtr_email_click_logs WHERE email_id IN ($placeholders)", 195 $email_ids 196 ) 197 ); 192 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 193 $wpdb->query( $wpdb->prepare("DELETE FROM {$wpdb->prefix}emtr_email_click_logs WHERE email_id IN ($placeholders)", $email_ids ) ); 198 194 199 195 // Delete emails 200 $deleted = $wpdb->query( 201 $wpdb->prepare( 202 "DELETE FROM {$table_name} WHERE id IN ($placeholders)", 203 $email_ids 204 ) 205 ); 196 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 197 $deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM {$table_name} WHERE id IN ($placeholders)", $email_ids ) ); 206 198 207 199 return count( $emails ); … … 227 219 228 220 // Get emails to export 221 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 229 222 $emails = $wpdb->get_results( 230 $wpdb->prepare( 231 "SELECT * FROM {$table_name} 232 ORDER BY id DESC 233 LIMIT %d OFFSET %d", 223 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 224 $wpdb->prepare("SELECT * FROM {$table_name} ORDER BY id DESC LIMIT %d OFFSET %d", 234 225 $chunk_size, 235 226 $offset … … 243 234 244 235 // Append to CSV file 236 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen 245 237 $handle = fopen( $export_file, 'a' ); 246 238 … … 253 245 fputcsv( $handle, $email ); 254 246 } 255 247 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 256 248 fclose( $handle ); 257 249 … … 275 267 return 0; 276 268 } 277 269 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen 278 270 $handle = fopen( $import_file, 'r' ); 279 271 … … 298 290 299 291 // Insert email 292 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery 300 293 $wpdb->insert( $table_name, $data ); 301 294 $processed++; 302 295 } 303 296 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 304 297 fclose( $handle ); 305 298 -
email-tracker/trunk/src/core/class-name-space-auto-loader.php
r2670982 r3416646 103 103 104 104 105 throw new Exception( 'namespace ' . $namespace_class . ' can\'t be found! Path parsed: ' . $full_path);105 throw new Exception( esc_html( 'namespace ' . $namespace_class . ' can\'t be found! Path parsed: ' . $full_path ) ); 106 106 } 107 107 -
email-tracker/trunk/src/integrations/emtr.php
r3344738 r3416646 5 5 if ( !isset( $emtr ) ) { 6 6 // Include Freemius SDK. 7 require_once dirname( dirname( dirname( __FILE__ ) ) ) . '/ libs/freemius/start.php';7 require_once dirname( dirname( dirname( __FILE__ ) ) ) . '/vendor/freemius/wordpress-sdk/start.php'; 8 8 $emtr = fs_dynamic_init( array( 9 9 'id' => '1811', … … 11 11 'type' => 'plugin', 12 12 'public_key' => 'pk_1ed59e732da6955b547b2f0daa319', 13 'is_premium' => true,13 'is_premium' => false, 14 14 'premium_suffix' => 'Pro', 15 15 'has_addons' => false, -
email-tracker/trunk/src/model/class-trackemail.php
r3344738 r3416646 1 1 <?php 2 2 3 namespace PrashantWP\Email_Tracker\Model; 3 4 … … 8 9 * @subpackage model 9 10 */ 10 11 if ( ! defined( 'ABSPATH' ) ) { 12 exit;// Exit if accessed directly11 if ( !defined( 'ABSPATH' ) ) { 12 exit; 13 // Exit if accessed directly 13 14 } 14 15 15 use PrashantWP\Email_Tracker\Util; 16 17 16 class TrackEmail { 18 19 /** 20 * Email open log table name 21 * 22 * @var string 23 */ 24 private $eo_table_name; 25 26 /** 27 * Email table name 28 * 29 * @var string 30 */ 31 private $email_table_name; 32 33 /** 34 * Email open primary key 35 * 36 * @var string 37 */ 38 private $eo_pk; 39 40 /** 41 * Email open foreign key 42 * 43 * @var string 44 */ 45 private $eo_fk; 46 47 /** 48 * Rewrite URL for email open tracking 49 * 50 * @var string 51 */ 52 private $rw_url_email_open; 53 54 /** 55 * Track interval in hours 56 * 57 * @var int 58 */ 59 private $track_interval; 60 61 public function __construct() { 62 global $wpdb; 63 64 // Table Name 65 $this->eo_table_name = Util::emtr_get_table_name( 'track_email_open_log' ); 66 67 $this->email_table_name = Util::emtr_get_table_name( 'email' ); 68 $this->eo_pk = 'trkemail_id'; 69 $this->eo_fk = 'trkemail_email_id'; 70 $this->rw_url_email_open = '/track/e/o/'; 71 /* 72 * To set time difference between two read tracked 73 * @package email-read-tracker 74 * @subpackage model 75 */ 76 $this->track_interval = 0; // in hour 77 } 78 79 /** 80 * insert_email_open_log() 81 * 82 * @param array $POST = posted data 83 * @return true 84 * 85 * add log data for email opened by track image access request or by click on link in email 86 * check for last log during given track interval 87 * if last entry is less than given time than, will add new open log entry 88 */ 89 public function insert_email_open_log( $POST ) { 90 global $wpdb; 91 92 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is safely generated 93 $rs_email_cnt = $wpdb->get_var( 94 $wpdb->prepare( 95 "SELECT count(*) FROM {$this->email_table_name} WHERE email_id=%d", 96 intval( $POST['trkemail_email_id'] ) 97 ) 98 ); 99 100 /** 101 * If email is deleted, no need to track it 102 */ 103 if ( $rs_email_cnt == 0 ) { 104 return false; 105 } 106 107 $POST['trkemail_tacked_by'] = 'Image'; 108 109 // Get date time for given interval 110 $interval_date_time = gmdate( 'Y-m-d H:i:s', strtotime( sprintf( '-%d hours', $this->track_interval ) ) ); 111 112 // Set sql query parameters 113 $param = 'AND ' . $this->eo_fk . ' = %s AND trkemail_date_time > %s'; 114 115 // Get record 116 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is safely generated 117 $rs_cnt = $wpdb->get_var( 118 $wpdb->prepare( 119 "SELECT count(*) FROM {$this->eo_table_name} WHERE 1 {$param}", 120 $POST[ $this->eo_fk ], 121 $interval_date_time 122 ) 123 ); 124 125 if ( $rs_cnt == 0 ) { 126 $arr_insert = array( 127 $this->eo_fk => $POST[ $this->eo_fk ], 128 'trkemail_tacked_by' => $POST['trkemail_tacked_by'], 129 'trkemail_http_user_agent' => sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ), 130 'trkemail_ip_address' => $this->get_client_ip(), 131 'trkemail_date_time' => gmdate( 'Y-m-d H:i:s' ), 132 ); 133 134 $wpdb->insert( 135 $this->eo_table_name, 136 $arr_insert, 137 array( 138 '%s', 139 '%s', 140 '%s', 141 '%s', 142 ) 143 ); 144 145 unset( $arr_insert ); 146 } 147 return true; 148 } 149 150 /** 151 * Get tracking code 152 * 153 * @author Dinesh 154 * 155 * @param int $ldemail_id = Lead email id 156 * @return string image tag with track url 157 * 158 */ 159 public function get_track_code( $email_id ) { 160 161 return "<img src=\"" . esc_url( get_home_url() . $this->rw_url_email_open . $email_id . '/track-log' ) . "\" style=\"display:none;\" alt=\"track\" />"; 162 163 } 164 165 166 167 /** 168 * TrackEmail::Insert_Link_Click_Log() 169 * 170 * @param array $POST = posted value 171 * @return true 172 * 173 * add log for link clicked 174 */ 175 public function insert_link_click_log( $link_id ) { 176 if ( emtr()->is__premium_only() ) { 177 if ( emtr()->is_plan( 'pro', true ) ) { 178 $email_id = $GLOBALS['wpdb']->get_var( $GLOBALS['wpdb']->prepare( 'SELECT trklink_email_id FROM ' . Util::emtr_get_table_name( 'track_email_link_master' ) . ' WHERE trklink_id=%d', $link_id ) ); 179 self::insert_link_open_log( $email_id ); 180 $GLOBALS['wpdb']->insert( 181 Util::emtr_get_table_name( 'track_email_link_click_log' ), 182 array( 183 'trklinkclick_date_time' => gmdate( 'Y-m-d H:i:s' ), 184 'trklinkclick_http_user_agent' => sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ), 185 'trklinkclick_ip_address' => self::get_client_ip(), 186 'trklinkclick_trklink_id' => $link_id, 187 'trklinkclick_email_id' => $email_id, 188 189 ), 190 array( 191 '%s', 192 '%s', 193 '%s', 194 '%d', 195 '%d', 196 ) 197 ); 198 199 return true; 200 } 201 } 202 203 } 204 205 public function insert_link_open_log( $email_id ) { 206 207 $interval_date_time = gmdate( 'Y-m-d H:i:s', strtotime( gmdate( 'Y-m-d H:i:s' ) ) - ( 3600 * 60 ) ); 208 $client_ip = self::get_client_ip(); 209 210 $sql = $GLOBALS['wpdb']->prepare( 'SELECT count(*) as count FROM ' . Util::emtr_get_table_name( 'track_email_open_log' ) . ' WHERE trkemail_email_id=%d AND trkemail_ip_address = %s AND trkemail_date_time > %s', $email_id, $client_ip, $interval_date_time ); 211 212 $already_track = $GLOBALS['wpdb']->get_var( $sql ); 213 214 if ( ! $already_track ) { 215 $arr_insert = array( 216 'trkemail_email_id' => $email_id, 217 'trkemail_tacked_by' => 'link', 218 'trkemail_http_user_agent' => $_SERVER['HTTP_USER_AGENT'], 219 'trkemail_ip_address' => $this->get_client_ip(), 220 'trkemail_date_time' => gmdate( 'Y-m-d H:i:s' ), 221 ); 222 223 $GLOBALS['wpdb']->insert( 224 $this->eo_table_name, 225 $arr_insert, 226 array( 227 '%s', 228 '%s', 229 '%s', 230 '%s', 231 ) 232 ); 233 234 unset( $arr_insert ); 235 236 } 237 238 } 239 240 /** 241 * TrackEmail::GetLink() 242 * 243 * @param int $pk = ID of link 244 * @return href link | false 245 * 246 * @ check for link for given id and return if found and return false if not found 247 */ 248 public function get_link( $pk ) { 249 $link = $GLOBALS['wpdb'] 250 ->get_var( 251 $GLOBALS['wpdb']->prepare( 252 'SELECT trklink_link FROM ' . $GLOBALS['wpdb']->prefix . 'emtr_track_email_link_master WHERE trklink_id=%d', 253 intval( $pk ) 254 ) 255 ); 256 257 if ( ! empty( $link ) ) { 258 return $link; 259 } else { 260 return false; 261 } 262 } 263 264 /** 265 * TrackEmail::EmailLinkReplace() 266 * 267 * @param array $arrLeadEmail = array of lead email 268 * @return new email contain 269 * 270 * @ find all links in html contain and replace link with traking logic 271 * Also insert link information in database 272 */ 273 public function email_link_replace( $email_content, $email_id, $user_id ) { 274 /*$regex = "/<a.*?href=[\"']?([^>'\"]*)[\"']?[^>]*?>(.*?)<\/a>/i";*/ 275 $regex = "/<a.*?href=[\"']?(?!javascript:|#)([^>'\"]+)[\"']?[^>]*?>(.+?)<\/a>/i"; 276 preg_match_all( $regex, $email_content, $matches ); 277 $all_links = $matches[1]; 278 279 // Set populateSchema for table link master 280 foreach ( $all_links as $key => $link ) { 281 $GLOBALS['wpdb']->insert( 282 Util::emtr_get_table_name( 'track_email_link_master' ), 283 array( 284 'trklink_link' => $link, 285 'trklink_email_id' => intval( $email_id ), 286 'trklink_user_id' => intval( $user_id ), 287 ), 288 array( 289 '%s', 290 '%d', 291 '%d', 292 ) 293 ); 294 295 // generate new link 296 $link_id = $GLOBALS['wpdb']->insert_id; 297 $new_link = home_url( '/track/e/l/' . $link_id ); 298 299 // Exact match required and these are twice required 300 $email_content = str_replace( "'" . $link . "'", "'" . $new_link . "'", $email_content ); 301 $email_content = str_replace( '"' . $link . '"', '"' . $new_link . '"', $email_content ); 302 } 303 304 return stripslashes( $email_content ); 305 } 306 307 public function get_link_log( $email_id ) { 308 $sql = $GLOBALS['wpdb']->prepare( 309 'SELECT TEM.*, 17 /** 18 * Email open log table name 19 * 20 * @var string 21 */ 22 private $eo_table_name; 23 24 /** 25 * Email table name 26 * 27 * @var string 28 */ 29 private $email_table_name; 30 31 /** 32 * Email open primary key 33 * 34 * @var string 35 */ 36 private $eo_pk; 37 38 /** 39 * Email open foreign key 40 * 41 * @var string 42 */ 43 private $eo_fk; 44 45 /** 46 * Rewrite URL for email open tracking 47 * 48 * @var string 49 */ 50 private $rw_url_email_open; 51 52 /** 53 * Track interval in hours 54 * 55 * @var int 56 */ 57 private $track_interval; 58 59 public function __construct() { 60 global $wpdb; 61 // Table Name 62 $this->eo_table_name = Util::emtr_get_table_name( 'track_email_open_log' ); 63 $this->email_table_name = Util::emtr_get_table_name( 'email' ); 64 $this->eo_pk = 'trkemail_id'; 65 $this->eo_fk = 'trkemail_email_id'; 66 $this->rw_url_email_open = '/track/e/o/'; 67 /* 68 * To set time difference between two read tracked 69 * @package email-read-tracker 70 * @subpackage model 71 */ 72 $this->track_interval = 0; 73 // in hour 74 } 75 76 /** 77 * insert_email_open_log() 78 * 79 * @param array $POST = posted data 80 * @return true 81 * 82 * add log data for email opened by track image access request or by click on link in email 83 * check for last log during given track interval 84 * if last entry is less than given time than, will add new open log entry 85 */ 86 public function insert_email_open_log( $POST ) { 87 global $wpdb; 88 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name is safely generated 89 $rs_email_cnt = $wpdb->get_var( 90 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery, PluginCheck.Security.DirectDB.UnescapedDBParameter 91 $wpdb->prepare( 92 "SELECT count(*) FROM " . $this->email_table_name . " WHERE email_id = %d", 93 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared 94 intval( sanitize_text_field( $POST['trkemail_email_id'] ) ) 95 ) 96 ); 97 /** 98 * If email is deleted, no need to track it 99 */ 100 if ( $rs_email_cnt == 0 ) { 101 return false; 102 } 103 $POST['trkemail_tacked_by'] = 'Image'; 104 // Get date time for given interval 105 $interval_date_time = gmdate( 'Y-m-d H:i:s', strtotime( sprintf( '-%d hours', $this->track_interval ) ) ); 106 // Set sql query parameters 107 $param = 'AND ' . $this->eo_fk . ' = %s AND trkemail_date_time > %s'; 108 // Get record 109 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 110 $rs_cnt = $wpdb->get_var( 111 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare 112 $wpdb->prepare( "SELECT count(*) FROM " . $this->eo_table_name . " WHERE 1 {$param}", sanitize_text_field( $POST[$this->eo_fk] ), $interval_date_time ) 113 ); 114 if ( $rs_cnt == 0 ) { 115 $arr_insert = array( 116 $this->eo_fk => intval( sanitize_text_field( wp_unslash( $POST[$this->eo_fk] ) ) ), 117 'trkemail_tacked_by' => sanitize_text_field( wp_unslash( $POST['trkemail_tacked_by'] ) ), 118 'trkemail_http_user_agent' => ( !empty( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '' ), 119 'trkemail_ip_address' => $this->get_client_ip(), 120 'trkemail_date_time' => gmdate( 'Y-m-d H:i:s' ), 121 ); 122 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery 123 $wpdb->insert( $this->eo_table_name, $arr_insert, array( 124 '%d', 125 '%s', 126 '%s', 127 '%s', 128 '%s' 129 ) ); 130 unset($arr_insert); 131 } 132 return true; 133 } 134 135 /** 136 * Get tracking code 137 * 138 * @author Dinesh 139 * 140 * @param int $ldemail_id = Lead email id 141 * @return string image tag with track url 142 * 143 */ 144 public function get_track_code( $email_id ) { 145 return "<img src=\"" . esc_url( get_home_url() . $this->rw_url_email_open . $email_id . '/track-log' ) . "\" style=\"display:none;\" alt=\"track\" />"; 146 } 147 148 /** 149 * TrackEmail::Insert_Link_Click_Log() 150 * 151 * @param array $POST = posted value 152 * @return true 153 * 154 * add log for link clicked 155 */ 156 public function insert_link_click_log( $link_id ) { 157 } 158 159 public function insert_link_open_log( $email_id ) { 160 $interval_date_time = gmdate( 'Y-m-d H:i:s', strtotime( gmdate( 'Y-m-d H:i:s' ) ) - 3600 * 60 ); 161 $client_ip = self::get_client_ip(); 162 $sql = $GLOBALS['wpdb']->prepare( 163 'SELECT count(*) as count FROM ' . Util::emtr_get_table_name( 'track_email_open_log' ) . ' WHERE trkemail_email_id=%d AND trkemail_ip_address = %s AND trkemail_date_time > %s', 164 $email_id, 165 $client_ip, 166 $interval_date_time 167 ); 168 $already_track = $GLOBALS['wpdb']->get_var( $sql ); 169 if ( !$already_track ) { 170 $arr_insert = array( 171 'trkemail_email_id' => $email_id, 172 'trkemail_tacked_by' => 'link', 173 'trkemail_http_user_agent' => ( !empty( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '' ), 174 'trkemail_ip_address' => $this->get_client_ip(), 175 'trkemail_date_time' => gmdate( 'Y-m-d H:i:s' ), 176 ); 177 $GLOBALS['wpdb']->insert( $this->eo_table_name, $arr_insert, array( 178 '%s', 179 '%s', 180 '%s', 181 '%s' 182 ) ); 183 unset($arr_insert); 184 } 185 } 186 187 /** 188 * TrackEmail::GetLink() 189 * 190 * @param int $pk = ID of link 191 * @return href link | false 192 * 193 * @ check for link for given id and return if found and return false if not found 194 */ 195 public function get_link( $pk ) { 196 $link = $GLOBALS['wpdb']->get_var( $GLOBALS['wpdb']->prepare( 'SELECT trklink_link FROM ' . $GLOBALS['wpdb']->prefix . 'emtr_track_email_link_master WHERE trklink_id = %d', intval( $pk ) ) ); 197 if ( !empty( $link ) ) { 198 return $link; 199 } else { 200 return false; 201 } 202 } 203 204 /** 205 * TrackEmail::EmailLinkReplace() 206 * 207 * @param array $arrLeadEmail = array of lead email 208 * @return new email contain 209 * 210 * @ find all links in html contain and replace link with traking logic 211 * Also insert link information in database 212 */ 213 public function email_link_replace( $email_content, $email_id, $user_id ) { 214 /*$regex = "/<a.*?href=[\"']?([^>'\"]*)[\"']?[^>]*?>(.*?)<\/a>/i";*/ 215 $regex = "/<a.*?href=[\"']?(?!javascript:|#)([^>'\"]+)[\"']?[^>]*?>(.+?)<\\/a>/i"; 216 preg_match_all( $regex, $email_content, $matches ); 217 $all_links = $matches[1]; 218 // Set populateSchema for table link master 219 foreach ( $all_links as $key => $link ) { 220 $GLOBALS['wpdb']->insert( Util::emtr_get_table_name( 'track_email_link_master' ), array( 221 'trklink_link' => $link, 222 'trklink_email_id' => intval( $email_id ), 223 'trklink_user_id' => intval( $user_id ), 224 ), array('%s', '%d', '%d') ); 225 // generate new link 226 $link_id = $GLOBALS['wpdb']->insert_id; 227 $new_link = home_url( '/track/e/l/' . $link_id ); 228 // Exact match required and these are twice required 229 $email_content = str_replace( "'" . $link . "'", "'" . $new_link . "'", $email_content ); 230 $email_content = str_replace( '"' . $link . '"', '"' . $new_link . '"', $email_content ); 231 } 232 return stripslashes( $email_content ); 233 } 234 235 public function get_link_log( $email_id ) { 236 $sql = $GLOBALS['wpdb']->prepare( 'SELECT TEM.*, 310 237 ( 311 238 SELECT COUNT(*) FROM ' . Util::emtr_get_table_name( 'track_email_link_click_log' ) . ' TEC … … 316 243 WHERE TEC.trklinkclick_trklink_id = TEM.trklink_id 317 244 ) AS last_clicked 318 FROM ' . Util::emtr_get_table_name( 'track_email_link_master' ) . ' TEM WHERE TEM.trklink_email_id = %d', 319 intval( $email_id ) 320 ); 321 322 // Execute query 323 $rs = $GLOBALS['wpdb']->get_results( $sql, ARRAY_A ); 324 325 return $rs; 326 } 327 328 public function get_email_view_data( $email_id ) { 329 $item = $GLOBALS['wpdb']->get_row( 330 $GLOBALS['wpdb']->prepare( 331 'SELECT E.*, 245 FROM ' . Util::emtr_get_table_name( 'track_email_link_master' ) . ' TEM WHERE TEM.trklink_email_id = %d', intval( $email_id ) ); 246 // Execute query 247 $rs = $GLOBALS['wpdb']->get_results( $sql, ARRAY_A ); 248 return $rs; 249 } 250 251 public function get_email_view_data( $email_id ) { 252 $item = $GLOBALS['wpdb']->get_row( $GLOBALS['wpdb']->prepare( 'SELECT E.*, 332 253 (SELECT count(*) FROM ' . Util::emtr_get_table_name( 'track_email_open_log' ) . ' EOC WHERE EOC.trkemail_email_id = E.email_id) AS view_count, 333 254 (SELECT GROUP_CONCAT(trkemail_date_time) FROM ' . Util::emtr_get_table_name( 'track_email_open_log' ) . ' EOD WHERE EOD.trkemail_email_id = E.email_id ORDER BY EOD.trkemail_date_time DESC) AS view_date_time 334 FROM ' . Util::emtr_get_table_name( 'email' ) . ' E WHERE 1 AND E.email_id=%d', 335 $email_id 336 ), 337 ARRAY_A 338 ); 339 return $item; 340 } 341 342 /** 343 * get_client_ip() 344 * 345 * @return ip address 346 * 347 * to get ip address of tracked email when it will be read 348 */ 349 function get_client_ip() { 350 $ret_ip = '127.0.0.1'; 351 $fields = array( 352 'HTTP_CF_CONNECTING_IP', 353 'HTTP_CLIENT_IP', 354 'HTTP_X_FORWARDED_FOR', 355 'HTTP_X_FORWARDED', 356 'HTTP_FORWARDED_FOR', 357 'HTTP_FORWARDED', 358 'REMOTE_ADDR', 359 ); 360 361 foreach ( $fields as $ip_field ) { 362 if ( ! empty( $_SERVER[ $ip_field ] ) ) { 363 $ret_ip = $_SERVER[ $ip_field ]; 364 break; 365 } 366 } 367 255 FROM ' . Util::emtr_get_table_name( 'email' ) . ' E WHERE 1 AND E.email_id = %d', $email_id ), ARRAY_A ); 256 return $item; 257 } 258 259 /** 260 * get_client_ip() 261 * 262 * @return ip address 263 * 264 * to get ip address of tracked email when it will be read 265 */ 266 function get_client_ip() { 267 $ret_ip = '127.0.0.1'; 268 $fields = array( 269 'HTTP_CF_CONNECTING_IP', 270 'HTTP_CLIENT_IP', 271 'HTTP_X_FORWARDED_FOR', 272 'HTTP_X_FORWARDED', 273 'HTTP_FORWARDED_FOR', 274 'HTTP_FORWARDED', 275 'REMOTE_ADDR' 276 ); 277 foreach ( $fields as $ip_field ) { 278 if ( !empty( $_SERVER[$ip_field] ) ) { 279 $ret_ip = sanitize_text_field( wp_unslash( $_SERVER[$ip_field] ) ); 280 break; 281 } 282 } 368 283 if ( stristr( $ret_ip, ',' ) ) { 369 $ret_ip = trim( reset( ( explode(',', $ret_ip ) ) ) ); 370 } 371 372 if( strpos( $ret_ip, '.' ) !== FALSE && strpos( $ret_ip, ':' ) !== FALSE ) { 284 $ret_ip = trim( reset( explode( ',', $ret_ip ) ) ); 285 } 286 if ( strpos( $ret_ip, '.' ) !== FALSE && strpos( $ret_ip, ':' ) !== FALSE ) { 373 287 //likely ipv4 address with port 374 $ret_ip = preg_replace('/:\d+$/', '', $ret_ip); //Strip off port 375 } 376 377 if ( '::1' == $ret_ip ) { 378 $ret_ip = '127.0.0.1'; 379 } 380 381 if ( filter_var( $ret_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) { 288 $ret_ip = preg_replace( '/:\\d+$/', '', $ret_ip ); 289 //Strip off port 290 } 291 if ( '::1' == $ret_ip ) { 292 $ret_ip = '127.0.0.1'; 293 } 294 if ( filter_var( $ret_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) { 382 295 return $ret_ip; 383 } else if ( filter_var( $ret_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ){384 return $ret_ip;385 }386 387 388 return '127.0.0.1';389 }296 } else { 297 if ( filter_var( $ret_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) { 298 return $ret_ip; 299 } 300 } 301 return '127.0.0.1'; 302 } 390 303 391 304 } -
email-tracker/trunk/track-email.php
r3344738 r3416646 1 1 <?php 2 2 3 /** 3 4 * To track email when email will be read … … 6 7 * @subpackage track-email 7 8 */ 8 9 9 /* 10 10 * To access EMTR_Model function to call model object 11 11 */ 12 if ( ! defined( 'ABSPATH' ) ) { 13 exit; // Exit if accessed directly 12 if ( !defined( 'ABSPATH' ) ) { 13 exit; 14 // Exit if accessed directly 14 15 } 15 16 $Action = sanitize_text_field( get_query_var( 'action', '' ) ); 17 $PK = intval( get_query_var( 'pk', '' ) ); 18 19 if ( $PK == 0 ) { 20 die; 21 } 22 16 $emtr_action = sanitize_text_field( get_query_var( 'action', '' ) ); 17 $emtr_pk = intval( get_query_var( 'pk', '' ) ); 18 if ( $emtr_pk == 0 ) { 19 die; 20 } 23 21 /* 24 22 * Display email track image 25 23 */ 26 24 // If email has been opened 27 if ( $Action == 'o' ) { 28 // Add Email Open Log 29 $POST['trkemail_email_id'] = $PK; 30 \PrashantWP\Email_Tracker\Factory::get( '\PrashantWP\Email_Tracker\Model\TrackEmail' )->insert_email_open_log( $POST ); 31 32 /* 33 $filename = __DIR__ . '/images/track-log.png'; 34 $s_code = file_get_contents( $filename ); 35 */ 36 header( 'Content-Type: image/png' ); 37 header( 'Pragma-directive: no-cache' ); 38 header( 'Cache-directive: no-cache' ); 39 header( 'Cache-control: no-cache' ); 40 header( 'Pragma: no-cache' ); 41 header( 'Expires: 0' ); 42 header( 'Content-Length: ' . 921 ); 43 // track-log.png base64 encoded value 44 echo base64_decode( "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAFoEvQfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NUQ4RTg0RkQxQjZBMTFFM0EyMjZEMEI1RDQxQTNEODgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NUQ4RTg0RkUxQjZBMTFFM0EyMjZEMEI1RDQxQTNEODgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1RDhFODRGQjFCNkExMUUzQTIyNkQwQjVENDFBM0Q4OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1RDhFODRGQzFCNkExMUUzQTIyNkQwQjVENDFBM0Q4OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmpagdgAAAANSURBVHjaY/7//z8DAAkLAwFJ9B4LAAAAAElFTkSuQmCC" ); 45 die; 46 } elseif ( $Action == 'l' ) { 47 48 $model_trackemail = \PrashantWP\Email_Tracker\Factory::get( '\PrashantWP\Email_Tracker\Model\TrackEmail' ); 49 $link = $model_trackemail->get_link( $PK ); 50 if ( $link != false ) { 51 if ( emtr()->is__premium_only() ) { 52 if ( emtr()->is_plan( 'pro', true ) || emtr()->is_trial() ) { 53 $model_trackemail->insert_link_click_log( $PK ); 54 } 55 } 56 $link = html_entity_decode( $link ); 57 // Redirect to main link 58 header( "location: $link" ); 59 die; 60 } 25 if ( $emtr_action == 'o' ) { 26 // Add Email Open Log 27 $EMTR_POST['trkemail_email_id'] = $emtr_pk; 28 \PrashantWP\Email_Tracker\Factory::get( '\\PrashantWP\\Email_Tracker\\Model\\TrackEmail' )->insert_email_open_log( $EMTR_POST ); 29 /* 30 $filename = __DIR__ . '/images/track-log.png'; 31 $s_code = file_get_contents( $filename ); 32 */ 33 header( 'Content-Type: image/png' ); 34 header( 'Pragma-directive: no-cache' ); 35 header( 'Cache-directive: no-cache' ); 36 header( 'Cache-control: no-cache' ); 37 header( 'Pragma: no-cache' ); 38 header( 'Expires: 0' ); 39 header( 'Content-Length: ' . 921 ); 40 // track-log.png base64 encoded value 41 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- track-log.png base64 decode. 42 echo base64_decode( esc_html( "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAFoEvQfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NUQ4RTg0RkQxQjZBMTFFM0EyMjZEMEI1RDQxQTNEODgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NUQ4RTg0RkUxQjZBMTFFM0EyMjZEMEI1RDQxQTNEODgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1RDhFODRGQjFCNkExMUUzQTIyNkQwQjVENDFBM0Q4OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1RDhFODRGQzFCNkExMUUzQTIyNkQwQjVENDFBM0Q4OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmpagdgAAAANSURBVHjaY/7//z8DAAkLAwFJ9B4LAAAAAElFTkSuQmCC" ) ); 43 die; 44 } elseif ( $emtr_action == 'l' ) { 45 $emtr_model_trackemail = \PrashantWP\Email_Tracker\Factory::get( '\\PrashantWP\\Email_Tracker\\Model\\TrackEmail' ); 46 $link = $emtr_model_trackemail->get_link( $emtr_pk ); 47 if ( $link != false ) { 48 $link = html_entity_decode( $link ); 49 // Redirect to main link 50 header( "location: {$link}" ); 51 die; 52 } 61 53 } 62 -
email-tracker/trunk/vendor/autoload.php
r2728263 r3416646 3 3 // autoload.php @generated by Composer 4 4 5 if (PHP_VERSION_ID < 50600) { 6 if (!headers_sent()) { 7 header('HTTP/1.1 500 Internal Server Error'); 8 } 9 $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; 10 if (!ini_get('display_errors')) { 11 if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { 12 fwrite(STDERR, $err); 13 } elseif (!headers_sent()) { 14 echo $err; 15 } 16 } 17 throw new RuntimeException($err); 18 } 19 5 20 require_once __DIR__ . '/composer/autoload_real.php'; 6 21 -
email-tracker/trunk/vendor/composer/ClassLoader.php
r2671016 r3416646 43 43 class ClassLoader 44 44 { 45 /** @var \Closure(string):void */ 46 private static $includeFile; 47 48 /** @var string|null */ 49 private $vendorDir; 50 45 51 // PSR-4 52 /** 53 * @var array<string, array<string, int>> 54 */ 46 55 private $prefixLengthsPsr4 = array(); 56 /** 57 * @var array<string, list<string>> 58 */ 47 59 private $prefixDirsPsr4 = array(); 60 /** 61 * @var list<string> 62 */ 48 63 private $fallbackDirsPsr4 = array(); 49 64 50 65 // PSR-0 66 /** 67 * List of PSR-0 prefixes 68 * 69 * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) 70 * 71 * @var array<string, array<string, list<string>>> 72 */ 51 73 private $prefixesPsr0 = array(); 74 /** 75 * @var list<string> 76 */ 52 77 private $fallbackDirsPsr0 = array(); 53 78 79 /** @var bool */ 54 80 private $useIncludePath = false; 81 82 /** 83 * @var array<string, string> 84 */ 55 85 private $classMap = array(); 86 87 /** @var bool */ 56 88 private $classMapAuthoritative = false; 89 90 /** 91 * @var array<string, bool> 92 */ 57 93 private $missingClasses = array(); 94 95 /** @var string|null */ 58 96 private $apcuPrefix; 59 97 98 /** 99 * @var array<string, self> 100 */ 101 private static $registeredLoaders = array(); 102 103 /** 104 * @param string|null $vendorDir 105 */ 106 public function __construct($vendorDir = null) 107 { 108 $this->vendorDir = $vendorDir; 109 self::initializeIncludeClosure(); 110 } 111 112 /** 113 * @return array<string, list<string>> 114 */ 60 115 public function getPrefixes() 61 116 { … … 67 122 } 68 123 124 /** 125 * @return array<string, list<string>> 126 */ 69 127 public function getPrefixesPsr4() 70 128 { … … 72 130 } 73 131 132 /** 133 * @return list<string> 134 */ 74 135 public function getFallbackDirs() 75 136 { … … 77 138 } 78 139 140 /** 141 * @return list<string> 142 */ 79 143 public function getFallbackDirsPsr4() 80 144 { … … 82 146 } 83 147 148 /** 149 * @return array<string, string> Array of classname => path 150 */ 84 151 public function getClassMap() 85 152 { … … 88 155 89 156 /** 90 * @param array $classMap Class to filename map 157 * @param array<string, string> $classMap Class to filename map 158 * 159 * @return void 91 160 */ 92 161 public function addClassMap(array $classMap) … … 103 172 * appending or prepending to the ones previously set for this prefix. 104 173 * 105 * @param string $prefix The prefix 106 * @param array|string $paths The PSR-0 root directories 107 * @param bool $prepend Whether to prepend the directories 174 * @param string $prefix The prefix 175 * @param list<string>|string $paths The PSR-0 root directories 176 * @param bool $prepend Whether to prepend the directories 177 * 178 * @return void 108 179 */ 109 180 public function add($prefix, $paths, $prepend = false) 110 181 { 182 $paths = (array) $paths; 111 183 if (!$prefix) { 112 184 if ($prepend) { 113 185 $this->fallbackDirsPsr0 = array_merge( 114 (array)$paths,186 $paths, 115 187 $this->fallbackDirsPsr0 116 188 ); … … 118 190 $this->fallbackDirsPsr0 = array_merge( 119 191 $this->fallbackDirsPsr0, 120 (array)$paths192 $paths 121 193 ); 122 194 } … … 127 199 $first = $prefix[0]; 128 200 if (!isset($this->prefixesPsr0[$first][$prefix])) { 129 $this->prefixesPsr0[$first][$prefix] = (array)$paths;201 $this->prefixesPsr0[$first][$prefix] = $paths; 130 202 131 203 return; … … 133 205 if ($prepend) { 134 206 $this->prefixesPsr0[$first][$prefix] = array_merge( 135 (array)$paths,207 $paths, 136 208 $this->prefixesPsr0[$first][$prefix] 137 209 ); … … 139 211 $this->prefixesPsr0[$first][$prefix] = array_merge( 140 212 $this->prefixesPsr0[$first][$prefix], 141 (array)$paths213 $paths 142 214 ); 143 215 } … … 148 220 * appending or prepending to the ones previously set for this namespace. 149 221 * 150 * @param string $prefix The prefix/namespace, with trailing '\\'151 * @param array|string $paths The PSR-4 base directories152 * @param bool $prepend Whether to prepend the directories222 * @param string $prefix The prefix/namespace, with trailing '\\' 223 * @param list<string>|string $paths The PSR-4 base directories 224 * @param bool $prepend Whether to prepend the directories 153 225 * 154 226 * @throws \InvalidArgumentException 227 * 228 * @return void 155 229 */ 156 230 public function addPsr4($prefix, $paths, $prepend = false) 157 231 { 232 $paths = (array) $paths; 158 233 if (!$prefix) { 159 234 // Register directories for the root namespace. 160 235 if ($prepend) { 161 236 $this->fallbackDirsPsr4 = array_merge( 162 (array)$paths,237 $paths, 163 238 $this->fallbackDirsPsr4 164 239 ); … … 166 241 $this->fallbackDirsPsr4 = array_merge( 167 242 $this->fallbackDirsPsr4, 168 (array)$paths243 $paths 169 244 ); 170 245 } … … 176 251 } 177 252 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 178 $this->prefixDirsPsr4[$prefix] = (array)$paths;253 $this->prefixDirsPsr4[$prefix] = $paths; 179 254 } elseif ($prepend) { 180 255 // Prepend directories for an already registered namespace. 181 256 $this->prefixDirsPsr4[$prefix] = array_merge( 182 (array)$paths,257 $paths, 183 258 $this->prefixDirsPsr4[$prefix] 184 259 ); … … 187 262 $this->prefixDirsPsr4[$prefix] = array_merge( 188 263 $this->prefixDirsPsr4[$prefix], 189 (array)$paths264 $paths 190 265 ); 191 266 } … … 196 271 * replacing any others previously set for this prefix. 197 272 * 198 * @param string $prefix The prefix 199 * @param array|string $paths The PSR-0 base directories 273 * @param string $prefix The prefix 274 * @param list<string>|string $paths The PSR-0 base directories 275 * 276 * @return void 200 277 */ 201 278 public function set($prefix, $paths) … … 212 289 * replacing any others previously set for this namespace. 213 290 * 214 * @param string $prefix The prefix/namespace, with trailing '\\'215 * @param array|string $paths The PSR-4 base directories291 * @param string $prefix The prefix/namespace, with trailing '\\' 292 * @param list<string>|string $paths The PSR-4 base directories 216 293 * 217 294 * @throws \InvalidArgumentException 295 * 296 * @return void 218 297 */ 219 298 public function setPsr4($prefix, $paths) … … 235 314 * 236 315 * @param bool $useIncludePath 316 * 317 * @return void 237 318 */ 238 319 public function setUseIncludePath($useIncludePath) … … 257 338 * 258 339 * @param bool $classMapAuthoritative 340 * 341 * @return void 259 342 */ 260 343 public function setClassMapAuthoritative($classMapAuthoritative) … … 277 360 * 278 361 * @param string|null $apcuPrefix 362 * 363 * @return void 279 364 */ 280 365 public function setApcuPrefix($apcuPrefix) … … 297 382 * 298 383 * @param bool $prepend Whether to prepend the autoloader or not 384 * 385 * @return void 299 386 */ 300 387 public function register($prepend = false) 301 388 { 302 389 spl_autoload_register(array($this, 'loadClass'), true, $prepend); 390 391 if (null === $this->vendorDir) { 392 return; 393 } 394 395 if ($prepend) { 396 self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; 397 } else { 398 unset(self::$registeredLoaders[$this->vendorDir]); 399 self::$registeredLoaders[$this->vendorDir] = $this; 400 } 303 401 } 304 402 305 403 /** 306 404 * Unregisters this instance as an autoloader. 405 * 406 * @return void 307 407 */ 308 408 public function unregister() 309 409 { 310 410 spl_autoload_unregister(array($this, 'loadClass')); 411 412 if (null !== $this->vendorDir) { 413 unset(self::$registeredLoaders[$this->vendorDir]); 414 } 311 415 } 312 416 … … 315 419 * 316 420 * @param string $class The name of the class 317 * @return bool|null True if loaded, null otherwise421 * @return true|null True if loaded, null otherwise 318 422 */ 319 423 public function loadClass($class) 320 424 { 321 425 if ($file = $this->findFile($class)) { 322 includeFile($file); 426 $includeFile = self::$includeFile; 427 $includeFile($file); 323 428 324 429 return true; 325 430 } 431 432 return null; 326 433 } 327 434 … … 368 475 } 369 476 477 /** 478 * Returns the currently registered loaders keyed by their corresponding vendor directories. 479 * 480 * @return array<string, self> 481 */ 482 public static function getRegisteredLoaders() 483 { 484 return self::$registeredLoaders; 485 } 486 487 /** 488 * @param string $class 489 * @param string $ext 490 * @return string|false 491 */ 370 492 private function findFileWithExtension($class, $ext) 371 493 { … … 433 555 return false; 434 556 } 557 558 /** 559 * @return void 560 */ 561 private static function initializeIncludeClosure() 562 { 563 if (self::$includeFile !== null) { 564 return; 565 } 566 567 /** 568 * Scope isolated include. 569 * 570 * Prevents access to $this/self from included files. 571 * 572 * @param string $file 573 * @return void 574 */ 575 self::$includeFile = \Closure::bind(static function($file) { 576 include $file; 577 }, null, null); 578 } 435 579 } 436 437 /**438 * Scope isolated include.439 *440 * Prevents access to $this/self from included files.441 */442 function includeFile($file)443 {444 include $file;445 } -
email-tracker/trunk/vendor/composer/InstalledVersions.php
r2728263 r3416646 1 1 <?php 2 2 3 4 5 6 7 8 9 10 11 3 /* 4 * This file is part of Composer. 5 * 6 * (c) Nils Adermann <naderman@naderman.de> 7 * Jordi Boggiano <j.boggiano@seld.be> 8 * 9 * For the full copyright and license information, please view the LICENSE 10 * file that was distributed with this source code. 11 */ 12 12 13 13 namespace Composer; 14 14 15 use Composer\Autoload\ClassLoader; 15 16 use Composer\Semver\VersionParser; 16 17 17 18 19 20 21 18 /** 19 * This class is copied in every Composer installed project and available to all 20 * 21 * See also https://getcomposer.org/doc/07-runtime.md#installed-versions 22 * 23 * To require its presence, you can require `composer-runtime-api ^2.0` 24 * 25 * @final 26 */ 22 27 class InstalledVersions 23 28 { 24 private static $installed = array ( 25 'root' => 26 array ( 27 'pretty_version' => 'dev-master', 28 'version' => 'dev-master', 29 'aliases' => 30 array ( 31 ), 32 'reference' => '18628208849f05a34875e772b17d7acd85960e3b', 33 'name' => 'prashant/email-tracker', 34 ), 35 'versions' => 36 array ( 37 'prashant/email-tracker' => 38 array ( 39 'pretty_version' => 'dev-master', 40 'version' => 'dev-master', 41 'aliases' => 42 array ( 43 ), 44 'reference' => '18628208849f05a34875e772b17d7acd85960e3b', 45 ), 46 'soundasleep/html2text' => 47 array ( 48 'pretty_version' => '1.1.0', 49 'version' => '1.1.0.0', 50 'aliases' => 51 array ( 52 ), 53 'reference' => '3243a7107878a61685d2eccf99918d6479e039fc', 54 ), 55 ), 56 ); 57 58 59 60 61 62 63 64 public static function getInstalledPackages() 65 { 66 return array_keys(self::$installed['versions']); 29 /** 30 * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to 31 * @internal 32 */ 33 private static $selfDir = null; 34 35 /** 36 * @var mixed[]|null 37 * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null 38 */ 39 private static $installed; 40 41 /** 42 * @var bool 43 */ 44 private static $installedIsLocalDir; 45 46 /** 47 * @var bool|null 48 */ 49 private static $canGetVendors; 50 51 /** 52 * @var array[] 53 * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}> 54 */ 55 private static $installedByVendor = array(); 56 57 /** 58 * Returns a list of all package names which are present, either by being installed, replaced or provided 59 * 60 * @return string[] 61 * @psalm-return list<string> 62 */ 63 public static function getInstalledPackages() 64 { 65 $packages = array(); 66 foreach (self::getInstalled() as $installed) { 67 $packages[] = array_keys($installed['versions']); 68 } 69 70 if (1 === \count($packages)) { 71 return $packages[0]; 72 } 73 74 return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); 75 } 76 77 /** 78 * Returns a list of all package names with a specific type e.g. 'library' 79 * 80 * @param string $type 81 * @return string[] 82 * @psalm-return list<string> 83 */ 84 public static function getInstalledPackagesByType($type) 85 { 86 $packagesByType = array(); 87 88 foreach (self::getInstalled() as $installed) { 89 foreach ($installed['versions'] as $name => $package) { 90 if (isset($package['type']) && $package['type'] === $type) { 91 $packagesByType[] = $name; 92 } 93 } 94 } 95 96 return $packagesByType; 97 } 98 99 /** 100 * Checks whether the given package is installed 101 * 102 * This also returns true if the package name is provided or replaced by another package 103 * 104 * @param string $packageName 105 * @param bool $includeDevRequirements 106 * @return bool 107 */ 108 public static function isInstalled($packageName, $includeDevRequirements = true) 109 { 110 foreach (self::getInstalled() as $installed) { 111 if (isset($installed['versions'][$packageName])) { 112 return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; 113 } 114 } 115 116 return false; 117 } 118 119 /** 120 * Checks whether the given package satisfies a version constraint 121 * 122 * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: 123 * 124 * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') 125 * 126 * @param VersionParser $parser Install composer/semver to have access to this class and functionality 127 * @param string $packageName 128 * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package 129 * @return bool 130 */ 131 public static function satisfies(VersionParser $parser, $packageName, $constraint) 132 { 133 $constraint = $parser->parseConstraints((string) $constraint); 134 $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); 135 136 return $provided->matches($constraint); 137 } 138 139 /** 140 * Returns a version constraint representing all the range(s) which are installed for a given package 141 * 142 * It is easier to use this via isInstalled() with the $constraint argument if you need to check 143 * whether a given version of a package is installed, and not just whether it exists 144 * 145 * @param string $packageName 146 * @return string Version constraint usable with composer/semver 147 */ 148 public static function getVersionRanges($packageName) 149 { 150 foreach (self::getInstalled() as $installed) { 151 if (!isset($installed['versions'][$packageName])) { 152 continue; 153 } 154 155 $ranges = array(); 156 if (isset($installed['versions'][$packageName]['pretty_version'])) { 157 $ranges[] = $installed['versions'][$packageName]['pretty_version']; 158 } 159 if (array_key_exists('aliases', $installed['versions'][$packageName])) { 160 $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); 161 } 162 if (array_key_exists('replaced', $installed['versions'][$packageName])) { 163 $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); 164 } 165 if (array_key_exists('provided', $installed['versions'][$packageName])) { 166 $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); 167 } 168 169 return implode(' || ', $ranges); 170 } 171 172 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 173 } 174 175 /** 176 * @param string $packageName 177 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present 178 */ 179 public static function getVersion($packageName) 180 { 181 foreach (self::getInstalled() as $installed) { 182 if (!isset($installed['versions'][$packageName])) { 183 continue; 184 } 185 186 if (!isset($installed['versions'][$packageName]['version'])) { 187 return null; 188 } 189 190 return $installed['versions'][$packageName]['version']; 191 } 192 193 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 194 } 195 196 /** 197 * @param string $packageName 198 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present 199 */ 200 public static function getPrettyVersion($packageName) 201 { 202 foreach (self::getInstalled() as $installed) { 203 if (!isset($installed['versions'][$packageName])) { 204 continue; 205 } 206 207 if (!isset($installed['versions'][$packageName]['pretty_version'])) { 208 return null; 209 } 210 211 return $installed['versions'][$packageName]['pretty_version']; 212 } 213 214 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 215 } 216 217 /** 218 * @param string $packageName 219 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference 220 */ 221 public static function getReference($packageName) 222 { 223 foreach (self::getInstalled() as $installed) { 224 if (!isset($installed['versions'][$packageName])) { 225 continue; 226 } 227 228 if (!isset($installed['versions'][$packageName]['reference'])) { 229 return null; 230 } 231 232 return $installed['versions'][$packageName]['reference']; 233 } 234 235 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 236 } 237 238 /** 239 * @param string $packageName 240 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. 241 */ 242 public static function getInstallPath($packageName) 243 { 244 foreach (self::getInstalled() as $installed) { 245 if (!isset($installed['versions'][$packageName])) { 246 continue; 247 } 248 249 return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; 250 } 251 252 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 253 } 254 255 /** 256 * @return array 257 * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} 258 */ 259 public static function getRootPackage() 260 { 261 $installed = self::getInstalled(); 262 263 return $installed[0]['root']; 264 } 265 266 /** 267 * Returns the raw installed.php data for custom implementations 268 * 269 * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. 270 * @return array[] 271 * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} 272 */ 273 public static function getRawData() 274 { 275 @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); 276 277 if (null === self::$installed) { 278 // only require the installed.php file if this file is loaded from its dumped location, 279 // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 280 if (substr(__DIR__, -8, 1) !== 'C') { 281 self::$installed = include __DIR__ . '/installed.php'; 282 } else { 283 self::$installed = array(); 284 } 285 } 286 287 return self::$installed; 288 } 289 290 /** 291 * Returns the raw data of all installed.php which are currently loaded for custom implementations 292 * 293 * @return array[] 294 * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}> 295 */ 296 public static function getAllRawData() 297 { 298 return self::getInstalled(); 299 } 300 301 /** 302 * Lets you reload the static array from another file 303 * 304 * This is only useful for complex integrations in which a project needs to use 305 * this class but then also needs to execute another project's autoloader in process, 306 * and wants to ensure both projects have access to their version of installed.php. 307 * 308 * A typical case would be PHPUnit, where it would need to make sure it reads all 309 * the data it needs from this class, then call reload() with 310 * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure 311 * the project in which it runs can then also use this class safely, without 312 * interference between PHPUnit's dependencies and the project's dependencies. 313 * 314 * @param array[] $data A vendor/composer/installed.php data set 315 * @return void 316 * 317 * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data 318 */ 319 public static function reload($data) 320 { 321 self::$installed = $data; 322 self::$installedByVendor = array(); 323 324 // when using reload, we disable the duplicate protection to ensure that self::$installed data is 325 // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not, 326 // so we have to assume it does not, and that may result in duplicate data being returned when listing 327 // all installed packages for example 328 self::$installedIsLocalDir = false; 329 } 330 331 /** 332 * @return string 333 */ 334 private static function getSelfDir() 335 { 336 if (self::$selfDir === null) { 337 self::$selfDir = strtr(__DIR__, '\\', '/'); 338 } 339 340 return self::$selfDir; 341 } 342 343 /** 344 * @return array[] 345 * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}> 346 */ 347 private static function getInstalled() 348 { 349 if (null === self::$canGetVendors) { 350 self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); 351 } 352 353 $installed = array(); 354 $copiedLocalDir = false; 355 356 if (self::$canGetVendors) { 357 $selfDir = self::getSelfDir(); 358 foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { 359 $vendorDir = strtr($vendorDir, '\\', '/'); 360 if (isset(self::$installedByVendor[$vendorDir])) { 361 $installed[] = self::$installedByVendor[$vendorDir]; 362 } elseif (is_file($vendorDir.'/composer/installed.php')) { 363 /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */ 364 $required = require $vendorDir.'/composer/installed.php'; 365 self::$installedByVendor[$vendorDir] = $required; 366 $installed[] = $required; 367 if (self::$installed === null && $vendorDir.'/composer' === $selfDir) { 368 self::$installed = $required; 369 self::$installedIsLocalDir = true; 370 } 371 } 372 if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) { 373 $copiedLocalDir = true; 374 } 375 } 376 } 377 378 if (null === self::$installed) { 379 // only require the installed.php file if this file is loaded from its dumped location, 380 // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 381 if (substr(__DIR__, -8, 1) !== 'C') { 382 /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */ 383 $required = require __DIR__ . '/installed.php'; 384 self::$installed = $required; 385 } else { 386 self::$installed = array(); 387 } 388 } 389 390 if (self::$installed !== array() && !$copiedLocalDir) { 391 $installed[] = self::$installed; 392 } 393 394 return $installed; 395 } 67 396 } 68 69 70 71 72 73 74 75 76 77 public static function isInstalled($packageName)78 {79 return isset(self::$installed['versions'][$packageName]);80 }81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 public static function satisfies(VersionParser $parser, $packageName, $constraint)96 {97 $constraint = $parser->parseConstraints($constraint);98 $provided = $parser->parseConstraints(self::getVersionRanges($packageName));99 100 return $provided->matches($constraint);101 }102 103 104 105 106 107 108 109 110 111 112 public static function getVersionRanges($packageName)113 {114 if (!isset(self::$installed['versions'][$packageName])) {115 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');116 }117 118 $ranges = array();119 if (isset(self::$installed['versions'][$packageName]['pretty_version'])) {120 $ranges[] = self::$installed['versions'][$packageName]['pretty_version'];121 }122 if (array_key_exists('aliases', self::$installed['versions'][$packageName])) {123 $ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']);124 }125 if (array_key_exists('replaced', self::$installed['versions'][$packageName])) {126 $ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']);127 }128 if (array_key_exists('provided', self::$installed['versions'][$packageName])) {129 $ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']);130 }131 132 return implode(' || ', $ranges);133 }134 135 136 137 138 139 public static function getVersion($packageName)140 {141 if (!isset(self::$installed['versions'][$packageName])) {142 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');143 }144 145 if (!isset(self::$installed['versions'][$packageName]['version'])) {146 return null;147 }148 149 return self::$installed['versions'][$packageName]['version'];150 }151 152 153 154 155 156 public static function getPrettyVersion($packageName)157 {158 if (!isset(self::$installed['versions'][$packageName])) {159 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');160 }161 162 if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) {163 return null;164 }165 166 return self::$installed['versions'][$packageName]['pretty_version'];167 }168 169 170 171 172 173 public static function getReference($packageName)174 {175 if (!isset(self::$installed['versions'][$packageName])) {176 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');177 }178 179 if (!isset(self::$installed['versions'][$packageName]['reference'])) {180 return null;181 }182 183 return self::$installed['versions'][$packageName]['reference'];184 }185 186 187 188 189 190 public static function getRootPackage()191 {192 return self::$installed['root'];193 }194 195 196 197 198 199 200 201 public static function getRawData()202 {203 return self::$installed;204 }205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 public static function reload($data)225 {226 self::$installed = $data;227 }228 } -
email-tracker/trunk/vendor/composer/autoload_classmap.php
r2653395 r3416646 3 3 // autoload_classmap.php @generated by Composer 4 4 5 $vendorDir = dirname( dirname(__FILE__));5 $vendorDir = dirname(__DIR__); 6 6 $baseDir = dirname($vendorDir); 7 7 -
email-tracker/trunk/vendor/composer/autoload_namespaces.php
r2653395 r3416646 3 3 // autoload_namespaces.php @generated by Composer 4 4 5 $vendorDir = dirname( dirname(__FILE__));5 $vendorDir = dirname(__DIR__); 6 6 $baseDir = dirname($vendorDir); 7 7 -
email-tracker/trunk/vendor/composer/autoload_psr4.php
r2653395 r3416646 3 3 // autoload_psr4.php @generated by Composer 4 4 5 $vendorDir = dirname( dirname(__FILE__));5 $vendorDir = dirname(__DIR__); 6 6 $baseDir = dirname($vendorDir); 7 7 -
email-tracker/trunk/vendor/composer/autoload_real.php
r2728263 r3416646 26 26 27 27 spl_autoload_register(array('ComposerAutoloaderInited4140dc717c0cb32f19cd1b5ae4af0a', 'loadClassLoader'), true, true); 28 self::$loader = $loader = new \Composer\Autoload\ClassLoader( );28 self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); 29 29 spl_autoload_unregister(array('ComposerAutoloaderInited4140dc717c0cb32f19cd1b5ae4af0a', 'loadClassLoader')); 30 30 31 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); 32 if ($useStaticLoader) { 33 require __DIR__ . '/autoload_static.php'; 34 35 call_user_func(\Composer\Autoload\ComposerStaticInited4140dc717c0cb32f19cd1b5ae4af0a::getInitializer($loader)); 36 } else { 37 $map = require __DIR__ . '/autoload_namespaces.php'; 38 foreach ($map as $namespace => $path) { 39 $loader->set($namespace, $path); 40 } 41 42 $map = require __DIR__ . '/autoload_psr4.php'; 43 foreach ($map as $namespace => $path) { 44 $loader->setPsr4($namespace, $path); 45 } 46 47 $classMap = require __DIR__ . '/autoload_classmap.php'; 48 if ($classMap) { 49 $loader->addClassMap($classMap); 50 } 51 } 31 require __DIR__ . '/autoload_static.php'; 32 call_user_func(\Composer\Autoload\ComposerStaticInited4140dc717c0cb32f19cd1b5ae4af0a::getInitializer($loader)); 52 33 53 34 $loader->register(true); 35 36 $filesToLoad = \Composer\Autoload\ComposerStaticInited4140dc717c0cb32f19cd1b5ae4af0a::$files; 37 $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { 38 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { 39 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; 40 41 require $file; 42 } 43 }, null, null); 44 foreach ($filesToLoad as $fileIdentifier => $file) { 45 $requireFile($fileIdentifier, $file); 46 } 54 47 55 48 return $loader; -
email-tracker/trunk/vendor/composer/autoload_static.php
r2728263 r3416646 7 7 class ComposerStaticInited4140dc717c0cb32f19cd1b5ae4af0a 8 8 { 9 public static $files = array ( 10 '8d50dc88e56bace65e1e72f6017983ed' => __DIR__ . '/..' . '/freemius/wordpress-sdk/start.php', 11 ); 12 9 13 public static $prefixLengthsPsr4 = array ( 10 14 'S' => -
email-tracker/trunk/vendor/composer/installed.json
r2653395 r3416646 2 2 "packages": [ 3 3 { 4 "name": "freemius/wordpress-sdk", 5 "version": "2.13.0", 6 "version_normalized": "2.13.0.0", 7 "source": { 8 "type": "git", 9 "url": "https://github.com/Freemius/wordpress-sdk.git", 10 "reference": "3cbe98b5bd0b0fb5ca4df97b8088592737ea4375" 11 }, 12 "dist": { 13 "type": "zip", 14 "url": "https://api.github.com/repos/Freemius/wordpress-sdk/zipball/3cbe98b5bd0b0fb5ca4df97b8088592737ea4375", 15 "reference": "3cbe98b5bd0b0fb5ca4df97b8088592737ea4375", 16 "shasum": "" 17 }, 18 "require": { 19 "php": ">=5.6" 20 }, 21 "require-dev": { 22 "dealerdirect/phpcodesniffer-composer-installer": "^1.0", 23 "phpcompatibility/php-compatibility": "^9.3", 24 "phpcompatibility/phpcompatibility-wp": "^2.1", 25 "phpstan/extension-installer": "^1.3", 26 "squizlabs/php_codesniffer": "^3.7", 27 "szepeviktor/phpstan-wordpress": "^1.3", 28 "wp-coding-standards/wpcs": "^2.3" 29 }, 30 "time": "2025-11-11T07:52:08+00:00", 31 "type": "library", 32 "installation-source": "dist", 33 "autoload": { 34 "files": [ 35 "start.php" 36 ] 37 }, 38 "notification-url": "https://packagist.org/downloads/", 39 "license": [ 40 "GPL-3.0-only" 41 ], 42 "description": "Freemius WordPress SDK", 43 "homepage": "https://freemius.com", 44 "keywords": [ 45 "freemius", 46 "plugin", 47 "sdk", 48 "theme", 49 "wordpress", 50 "wordpress-plugin", 51 "wordpress-theme" 52 ], 53 "support": { 54 "issues": "https://github.com/Freemius/wordpress-sdk/issues", 55 "source": "https://github.com/Freemius/wordpress-sdk/tree/2.13.0" 56 }, 57 "install-path": "../freemius/wordpress-sdk" 58 }, 59 { 4 60 "name": "soundasleep/html2text", 5 "version": " 1.1.0",6 "version_normalized": " 1.1.0.0",61 "version": "2.1.0", 62 "version_normalized": "2.1.0.0", 7 63 "source": { 8 64 "type": "git", 9 65 "url": "https://github.com/soundasleep/html2text.git", 10 "reference": " 3243a7107878a61685d2eccf99918d6479e039fc"66 "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3" 11 67 }, 12 68 "dist": { 13 69 "type": "zip", 14 "url": "https://api.github.com/repos/soundasleep/html2text/zipball/ 3243a7107878a61685d2eccf99918d6479e039fc",15 "reference": " 3243a7107878a61685d2eccf99918d6479e039fc",70 "url": "https://api.github.com/repos/soundasleep/html2text/zipball/83502b6f8f1aaef8e2e238897199d64f284b4af3", 71 "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3", 16 72 "shasum": "" 17 73 }, … … 19 75 "ext-dom": "*", 20 76 "ext-libxml": "*", 21 "php": " >=7.0"77 "php": "^7.3|^8.0" 22 78 }, 23 79 "require-dev": { 24 "php unit/phpunit": "~7.0",25 " soundasleep/component-tests": "~0.2"80 "phpstan/phpstan": "^1.9", 81 "phpunit/phpunit": "^7.0|^8.0|^9.0" 26 82 }, 27 "time": "20 19-02-15T01:44:54+00:00",83 "time": "2023-01-06T09:28:15+00:00", 28 84 "type": "library", 29 85 "installation-source": "dist", … … 55 111 "email": "support@jevon.org", 56 112 "issues": "https://github.com/soundasleep/html2text/issues", 57 "source": "https://github.com/soundasleep/html2text/tree/ master"113 "source": "https://github.com/soundasleep/html2text/tree/2.1.0" 58 114 }, 59 115 "install-path": "../soundasleep/html2text" -
email-tracker/trunk/vendor/composer/installed.php
r2728263 r3416646 1 <?php return array ( 2 'root' => 3 array ( 4 'pretty_version' => 'dev-master', 5 'version' => 'dev-master', 6 'aliases' => 7 array ( 1 <?php return array( 2 'root' => array( 3 'name' => 'prashant/email-tracker', 4 'pretty_version' => 'dev-master', 5 'version' => 'dev-master', 6 'reference' => '1b8fd6ea4ffc6e1e682ed4577c44f56f73d79fb4', 7 'type' => 'project', 8 'install_path' => __DIR__ . '/../../', 9 'aliases' => array(), 10 'dev' => true, 8 11 ), 9 'reference' => '18628208849f05a34875e772b17d7acd85960e3b', 10 'name' => 'prashant/email-tracker', 11 ), 12 'versions' => 13 array ( 14 'prashant/email-tracker' => 15 array ( 16 'pretty_version' => 'dev-master', 17 'version' => 'dev-master', 18 'aliases' => 19 array ( 20 ), 21 'reference' => '18628208849f05a34875e772b17d7acd85960e3b', 12 'versions' => array( 13 'freemius/wordpress-sdk' => array( 14 'pretty_version' => '2.13.0', 15 'version' => '2.13.0.0', 16 'reference' => '3cbe98b5bd0b0fb5ca4df97b8088592737ea4375', 17 'type' => 'library', 18 'install_path' => __DIR__ . '/../freemius/wordpress-sdk', 19 'aliases' => array(), 20 'dev_requirement' => false, 21 ), 22 'prashant/email-tracker' => array( 23 'pretty_version' => 'dev-master', 24 'version' => 'dev-master', 25 'reference' => '1b8fd6ea4ffc6e1e682ed4577c44f56f73d79fb4', 26 'type' => 'project', 27 'install_path' => __DIR__ . '/../../', 28 'aliases' => array(), 29 'dev_requirement' => false, 30 ), 31 'soundasleep/html2text' => array( 32 'pretty_version' => '2.1.0', 33 'version' => '2.1.0.0', 34 'reference' => '83502b6f8f1aaef8e2e238897199d64f284b4af3', 35 'type' => 'library', 36 'install_path' => __DIR__ . '/../soundasleep/html2text', 37 'aliases' => array(), 38 'dev_requirement' => false, 39 ), 22 40 ), 23 'soundasleep/html2text' =>24 array (25 'pretty_version' => '1.1.0',26 'version' => '1.1.0.0',27 'aliases' =>28 array (29 ),30 'reference' => '3243a7107878a61685d2eccf99918d6479e039fc',31 ),32 ),33 41 ); -
email-tracker/trunk/vendor/composer/platform_check.php
r2653395 r3416646 5 5 $issues = array(); 6 6 7 if (!(PHP_VERSION_ID >= 70 000)) {8 $issues[] = 'Your Composer dependencies require a PHP version ">= 7. 0.0". You are running ' . PHP_VERSION . '.';7 if (!(PHP_VERSION_ID >= 70300)) { 8 $issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.'; 9 9 } 10 10 -
email-tracker/trunk/vendor/soundasleep/html2text/.gitignore
r2653395 r3416646 4 4 vendor/ 5 5 **/*.DS_Store 6 .phpunit.result.cache 7 composer.lock -
email-tracker/trunk/vendor/soundasleep/html2text/README.md
r2653395 r3416646 1 html2text [](https://travis-ci.org/soundasleep/html2text) [](https://packagist.org/packages/soundasleep/html2text)1  [](https://packagist.org/packages/soundasleep/html2text) 2 2 ========= 3 3 … … 72 72 | **ignore_errors** | `false` | Set to `true` to ignore any XML parsing errors. | 73 73 | **drop_links** | `false` | Set to `true` to not render links as `[http://foo.com](My Link)`, but rather just `My Link`. | 74 | **char_set** | `'auto'` | Specify a specific character set. Pass multiple character sets (comma separated) to detect encoding, default is ASCII,UTF-8 | 74 75 75 76 Pass along options as a second argument to `convert`, for example: … … 91 92 ### Class 'DOMDocument' not found 92 93 93 You need to [install the PHP XML extension](https://github.com/soundasleep/html2text/issues/55) for your PHP version. e.g. `apt-get install php7. 1-xml`94 You need to [install the PHP XML extension](https://github.com/soundasleep/html2text/issues/55) for your PHP version. e.g. `apt-get install php7.4-xml` 94 95 95 96 ## License -
email-tracker/trunk/vendor/soundasleep/html2text/composer.json
r2653395 r3416646 22 22 }, 23 23 "require": { 24 "php": " >=7.0",24 "php": "^7.3|^8.0", 25 25 "ext-dom": "*", 26 26 "ext-libxml": "*" 27 27 }, 28 28 "require-dev": { 29 "phpunit/phpunit": " ~7.0",30 " soundasleep/component-tests": "~0.2"29 "phpunit/phpunit": "^7.0|^8.0|^9.0", 30 "phpstan/phpstan": "^1.9" 31 31 } 32 32 } -
email-tracker/trunk/vendor/soundasleep/html2text/src/Html2Text.php
r2653395 r3416646 5 5 class Html2Text { 6 6 7 public static function defaultOptions() { 8 return array( 7 /** @return array<string, bool | string> */ 8 public static function defaultOptions(): array { 9 return [ 9 10 'ignore_errors' => false, 10 11 'drop_links' => false, 11 ); 12 'char_set' => 'auto' 13 ]; 12 14 } 13 15 … … 23 25 * 24 26 * @param string $html the input HTML 25 * @param boolean $ignore_error Ignore xml parsing errors27 * @param boolean|array<string, bool | string> $options if boolean, Ignore xml parsing errors, else ['ignore_errors' => false, 'drop_links' => false, 'char_set' => 'auto'] 26 28 * @return string the HTML converted, as best as possible, to text 27 29 * @throws Html2TextException if the HTML could not be loaded as a {@link \DOMDocument} 28 30 */ 29 public static function convert( $html, $options = array()){31 public static function convert(string $html, $options = []): string { 30 32 31 33 if ($options === false || $options === true) { 32 34 // Using old style (< 1.0) of passing in options 33 $options = array('ignore_errors' => $options);35 $options = ['ignore_errors' => $options]; 34 36 } 35 37 … … 39 41 foreach ($options as $key => $value) { 40 42 if (!in_array($key, array_keys(static::defaultOptions()))) { 41 throw new \InvalidArgumentException("Unknown html2text option '$key' ");42 } 43 } 44 45 $is_office_document = s tatic::isOfficeDocument($html);43 throw new \InvalidArgumentException("Unknown html2text option '$key'. Valid options are " . implode(',', static::defaultOptions())); 44 } 45 } 46 47 $is_office_document = self::isOfficeDocument($html); 46 48 47 49 if ($is_office_document) { 48 50 // remove office namespace 49 $html = str_replace(array("<o:p>", "</o:p>"), "", $html); 50 } 51 52 $html = static::fixNewlines($html); 53 if (mb_detect_encoding($html, "UTF-8", true)) { 51 $html = str_replace(["<o:p>", "</o:p>"], "", $html); 52 } 53 54 $html = self::fixNewlines($html); 55 56 // use mb_convert_encoding for legacy versions of php 57 if (PHP_MAJOR_VERSION * 10 + PHP_MINOR_VERSION < 81 && mb_detect_encoding($html, "UTF-8", true)) { 54 58 $html = mb_convert_encoding($html, "HTML-ENTITIES", "UTF-8"); 55 59 } 56 60 57 $doc = s tatic::getDocument($html, $options['ignore_errors']);58 59 $output = s tatic::iterateOverNode($doc, null, false, $is_office_document, $options);61 $doc = self::getDocument($html, $options); 62 63 $output = self::iterateOverNode($doc, null, false, $is_office_document, $options); 60 64 61 65 // process output for whitespace/newlines 62 $output = s tatic::processWhitespaceNewlines($output);66 $output = self::processWhitespaceNewlines($output); 63 67 64 68 return $output; … … 73 77 * @return string the fixed text 74 78 */ 75 static function fixNewlines($text){79 public static function fixNewlines(string $text): string { 76 80 // replace \r\n to \n 77 81 $text = str_replace("\r\n", "\n", $text); … … 82 86 } 83 87 84 static function nbspCodes() { 85 return array( 88 /** @return array<string> */ 89 public static function nbspCodes(): array { 90 return [ 86 91 "\xc2\xa0", 87 92 "\u00a0", 88 ); 89 } 90 91 static function zwnjCodes() { 92 return array( 93 ]; 94 } 95 96 /** @return array<string> */ 97 public static function zwnjCodes(): array { 98 return [ 93 99 "\xe2\x80\x8c", 94 100 "\u200c", 95 );101 ]; 96 102 } 97 103 … … 102 108 * @return string the fixed text 103 109 */ 104 static function processWhitespaceNewlines($text){110 public static function processWhitespaceNewlines(string $text): string { 105 111 106 112 // remove excess spaces around tabs … … 116 122 // do it here so they do NOT get removed with other leading spaces, as they 117 123 // are sometimes used for indentation 118 $text = s tatic::renderText($text);124 $text = self::renderText($text); 119 125 120 126 // remove trailing whitespace … … 125 131 126 132 // unarmor pre blocks 127 $text = s tatic::fixNewLines($text);133 $text = self::fixNewLines($text); 128 134 129 135 // remove unnecessary empty lines … … 131 137 132 138 return $text; 139 } 140 141 /** 142 * Can we guess that this HTML is generated by Microsoft Office? 143 */ 144 public static function isOfficeDocument(string $html): bool { 145 return strpos($html, "urn:schemas-microsoft-com:office") !== false; 146 } 147 148 public static function isWhitespace(string $text): bool { 149 return strlen(trim(self::renderText($text), "\n\r\t ")) === 0; 133 150 } 134 151 … … 137 154 * 138 155 * @param string $html the input HTML 139 * @param boolean $ignore_error Ignore xml parsing errors156 * @param array<string, bool | string> $options 140 157 * @return \DOMDocument the parsed document tree 141 158 */ 142 static function getDocument($html, $ignore_error = false){159 private static function getDocument(string $html, array $options): \DOMDocument { 143 160 144 161 $doc = new \DOMDocument(); … … 160 177 } 161 178 162 if ($ignore_error) { 179 $header = ''; 180 // use char sets for modern versions of php 181 if (PHP_MAJOR_VERSION * 10 + PHP_MINOR_VERSION >= 81) { 182 // use specified char_set, or auto detect if not set 183 $char_set = ! empty($options['char_set']) ? $options['char_set'] : 'auto'; 184 if ('auto' === $char_set) { 185 $char_set = mb_detect_encoding($html); 186 } else if (strpos($char_set, ',')) { 187 mb_detect_order($char_set); 188 $char_set = mb_detect_encoding($html); 189 } 190 // turn off error detection for Windows-1252 legacy html 191 if (strpos($char_set, '1252')) { 192 $options['ignore_errors'] = true; 193 } 194 $header = '<?xml version="1.0" encoding="' . $char_set . '">'; 195 } 196 197 if (! empty($options['ignore_errors'])) { 163 198 $doc->strictErrorChecking = false; 164 199 $doc->recover = true; 165 200 $doc->xmlStandalone = true; 166 201 $old_internal_errors = libxml_use_internal_errors(true); 167 $load_result = $doc->loadHTML($h tml, LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NONET | LIBXML_PARSEHUGE);202 $load_result = $doc->loadHTML($header . $html, LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NONET | LIBXML_PARSEHUGE); 168 203 libxml_use_internal_errors($old_internal_errors); 169 204 } 170 205 else { 171 $load_result = $doc->loadHTML($h tml);206 $load_result = $doc->loadHTML($header . $html); 172 207 } 173 208 … … 177 212 178 213 return $doc; 179 }180 181 /**182 * Can we guess that this HTML is generated by Microsoft Office?183 */184 static function isOfficeDocument($html) {185 return strpos($html, "urn:schemas-microsoft-com:office") !== false;186 214 } 187 215 … … 194 222 * by a browser. 195 223 */ 196 static function renderText($text){197 $text = str_replace(s tatic::nbspCodes(), " ", $text);198 $text = str_replace(s tatic::zwnjCodes(), "", $text);224 private static function renderText(string $text): string { 225 $text = str_replace(self::nbspCodes(), " ", $text); 226 $text = str_replace(self::zwnjCodes(), "", $text); 199 227 return $text; 200 228 } 201 229 202 static function isWhitespace($text) { 203 return strlen(trim(static::renderText($text), "\n\r\t ")) === 0; 204 } 205 206 static function nextChildName($node) { 230 private static function nextChildName(?\DOMNode $node): ?string { 207 231 // get the next child 208 232 $nextNode = $node->nextSibling; 209 233 while ($nextNode != null) { 210 234 if ($nextNode instanceof \DOMText) { 211 if (!s tatic::isWhitespace($nextNode->wholeText)) {235 if (!self::isWhitespace($nextNode->wholeText)) { 212 236 break; 213 237 } … … 229 253 } 230 254 231 static function iterateOverNode($node, $prevName = null, $in_pre = false, $is_office_document = false, $options) { 255 /** @param array<string, bool | string> $options */ 256 private static function iterateOverNode(\DOMNode $node, ?string $prevName, bool $in_pre, bool $is_office_document, array $options): string { 232 257 if ($node instanceof \DOMText) { 233 258 // Replace whitespace characters with a space (equivilant to \s) 234 259 if ($in_pre) { 235 $text = "\n" . trim(s tatic::renderText($node->wholeText), "\n\r\t ") . "\n";260 $text = "\n" . trim(self::renderText($node->wholeText), "\n\r\t ") . "\n"; 236 261 237 262 // Remove trailing whitespace only … … 241 266 return str_replace("\n", "\r", $text); 242 267 243 } else { 244 $text = static::renderText($node->wholeText); 245 $text = preg_replace("/[\\t\\n\\f\\r ]+/im", " ", $text); 246 247 if (!static::isWhitespace($text) && ($prevName == 'p' || $prevName == 'div')) { 248 return "\n" . $text; 249 } 250 return $text; 251 } 268 } 269 $text = self::renderText($node->wholeText); 270 $text = preg_replace("/[\\t\\n\\f\\r ]+/im", " ", $text); 271 272 if (!self::isWhitespace($text) && ($prevName == 'p' || $prevName == 'div')) { 273 return "\n" . $text; 274 } 275 return $text; 252 276 } 253 277 … … 258 282 259 283 $name = strtolower($node->nodeName); 260 $nextName = s tatic::nextChildName($node);284 $nextName = self::nextChildName($node); 261 285 262 286 // start whitespace … … 303 327 // classname in any Microsoft export or outlook for a paragraph that behaves 304 328 // like a line return) we skip the first line returns and set the name to br. 329 // @phpstan-ignore-next-line 305 330 if ($is_office_document && $node->getAttribute('class') == 'MsoNormal') { 306 331 $output = ""; … … 342 367 343 368 $n = $node->childNodes->item(0); 344 $previousSiblingNames = array();369 $previousSiblingNames = []; 345 370 $previousSiblingName = null; 346 371 347 $parts = array();372 $parts = []; 348 373 $trailing_whitespace = 0; 349 374 350 375 while ($n != null) { 351 376 352 $text = s tatic::iterateOverNode($n, $previousSiblingName, $in_pre || $name == 'pre', $is_office_document, $options);377 $text = self::iterateOverNode($n, $previousSiblingName, $in_pre || $name == 'pre', $is_office_document, $options); 353 378 354 379 // Pass current node name to next child, as previousSibling does not appear to get populated 355 380 if ($n instanceof \DOMDocumentType 356 381 || $n instanceof \DOMProcessingInstruction 357 || ($n instanceof \DOMText && s tatic::isWhitespace($text))) {382 || ($n instanceof \DOMText && self::isWhitespace($text))) { 358 383 // Keep current previousSiblingName, these are invisible 359 384 $trailing_whitespace++; … … 412 437 case "a": 413 438 // links are returned in [text](link) format 439 // @phpstan-ignore-next-line 414 440 $href = $node->getAttribute("href"); 415 441 … … 421 447 422 448 // for linking images, the title of the <a> overrides the title of the <img> 449 // @phpstan-ignore-next-line 423 450 if ($node->getAttribute("title")) { 451 // @phpstan-ignore-next-line 424 452 $output = $node->getAttribute("title"); 425 453 } … … 427 455 428 456 // if there is no link text, but a title attr 457 // @phpstan-ignore-next-line 429 458 if (!$output && $node->getAttribute("title")) { 459 // @phpstan-ignore-next-line 430 460 $output = $node->getAttribute("title"); 431 461 } … … 433 463 if ($href == null) { 434 464 // it doesn't link anywhere 465 // @phpstan-ignore-next-line 435 466 if ($node->getAttribute("name") != null) { 436 467 if ($options['drop_links']) { … … 468 499 469 500 case "img": 501 // @phpstan-ignore-next-line 470 502 if ($node->getAttribute("title")) { 503 // @phpstan-ignore-next-line 471 504 $output = "[" . $node->getAttribute("title") . "]"; 505 // @phpstan-ignore-next-line 472 506 } elseif ($node->getAttribute("alt")) { 507 // @phpstan-ignore-next-line 473 508 $output = "[" . $node->getAttribute("alt") . "]"; 474 509 } else { … … 483 518 case "blockquote": 484 519 // process quoted text for whitespace/newlines 485 $output = s tatic::processWhitespaceNewlines($output);520 $output = self::processWhitespaceNewlines($output); 486 521 487 522 // add leading newline -
email-tracker/trunk/vendor/soundasleep/html2text/src/Html2TextException.php
r2653395 r3416646 5 5 class Html2TextException extends \Exception { 6 6 7 var $more_info; 7 /** @var string $more_info */ 8 public $more_info; 8 9 9 public function __construct( $message = "",$more_info = "") {10 public function __construct(string $message = "", string $more_info = "") { 10 11 parent::__construct($message); 11 12 $this->more_info = $more_info;
Note: See TracChangeset
for help on using the changeset viewer.