Plugin Directory

Changeset 3416646


Ignore:
Timestamp:
12/10/2025 05:43:50 PM (4 months ago)
Author:
pmbaldha
Message:

Email Tracker 5.3.16 version in Trunk

Location:
email-tracker/trunk
Files:
224 added
7 deleted
40 edited

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
     11module.exports = window["wp"]["apiFetch"];
     12
     13/***/ }),
     14
     15/***/ "@wordpress/components":
     16/*!************************************!*\
     17  !*** external ["wp","components"] ***!
     18  \************************************/
     19/***/ ((module) => {
     20
     21module.exports = window["wp"]["components"];
     22
     23/***/ }),
     24
     25/***/ "@wordpress/element":
     26/*!*********************************!*\
     27  !*** external ["wp","element"] ***!
     28  \*********************************/
     29/***/ ((module) => {
     30
     31module.exports = window["wp"]["element"];
     32
     33/***/ }),
     34
     35/***/ "@wordpress/i18n":
     36/*!******************************!*\
     37  !*** external ["wp","i18n"] ***!
     38  \******************************/
     39/***/ ((module) => {
     40
     41module.exports = window["wp"]["i18n"];
     42
     43/***/ }),
     44
     45/***/ "moment":
     46/*!*************************!*\
     47  !*** external "moment" ***!
     48  \*************************/
     49/***/ ((module) => {
     50
     51module.exports = window["moment"];
     52
     53/***/ }),
     54
     55/***/ "react/jsx-runtime":
     56/*!**********************************!*\
     57  !*** external "ReactJSXRuntime" ***!
     58  \**********************************/
     59/***/ ((module) => {
     60
     61module.exports = window["ReactJSXRuntime"];
     62
     63/***/ })
     64
     65/******/    });
     66/************************************************************************/
    267/******/    // The module cache
    3 /******/    var installedModules = {};
    4 /******/
     68/******/    var __webpack_module_cache__ = {};
     69/******/   
    570/******/    // The require function
    671/******/    function __webpack_require__(moduleId) {
    7 /******/
    872/******/        // 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;
    1176/******/        }
    1277/******/        // 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
    1681/******/            exports: {}
    1782/******/        };
    18 /******/
     83/******/   
    1984/******/        // 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/******/   
    2587/******/        // Return the exports of the module
    2688/******/        return module.exports;
    2789/******/    }
    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/******/   
    8691/************************************************************************/
    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/************************************************************************/
     133var __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(() => {
    148136/*!**********************!*\
    149137  !*** ./src/index.js ***!
    150138  \**********************/
    151 /*! no exports provided */
    152 /***/ (function(module, __webpack_exports__, __webpack_require__) {
    153 
    154 "use strict";
    155139__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__);
    173152
    174153
     
    180159
    181160
    182 class EmailModalView extends _wordpress_element__WEBPACK_IMPORTED_MODULE_2__["Component"] {
     161class EmailModalView extends _wordpress_element__WEBPACK_IMPORTED_MODULE_0__.Component {
    183162  constructor(props) {
    184163    super(props);
    185 
    186     _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1___default()(this, "setOpen", openFlag => {
    187       this.setState({
    188         isOpen: openFlag
    189       });
    190     });
    191 
    192     _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1___default()(this, "closeModal", () => {
    193       this.setOpen(false);
    194     });
    195 
    196164    this.state = {
    197165      isOpen: true,
     
    210178    };
    211179  }
    212 
    213180  componentDidMount() {
    214     _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_4___default()({
     181    _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2___default()({
    215182      path: '/email-tracker/v1/email/' + this.props.id + '/',
    216183      method: 'GET'
    217184    }).then(res => {
    218       this.setState({ ...res,
     185      this.setState({
     186        ...res,
    219187        isLoading: false
    220188      });
     
    226194    });
    227195  }
    228 
     196  setOpen = openFlag => {
     197    this.setState({
     198      isOpen: openFlag
     199    });
     200  };
     201  closeModal = () => {
     202    this.setOpen(false);
     203  };
    229204  render() {
    230205    const {
     
    233208      subject
    234209    } = 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);
    236211    const icon = 'email-alt';
    237212    const isDismissible = true;
     
    239214    const shouldCloseOnEsc = true;
    240215    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, {
    242217      icon: icon
    243218    }) : null;
     
    251226    };
    252227    let modalBody;
    253 
    254228    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, {
    256230        color: "blue",
    257231        size: "200"
    258232      });
    259233    } 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();
    261235      let read_log_panel_body;
    262 
    263236      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        });
    268247      } 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');
    270249      }
    271 
    272250      let state = this.state;
    273251      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      });
    312314    }
    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    });
    320325  }
    321 
    322326}
    323 
    324327window.EMTRLoadView = function EMTRLoadView(id, subject = '', to = '') {
    325328  let passProps = {
     
    328331    to
    329332  };
    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  }));
    333341  return false;
    334342};
    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;
    394347//# 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":";QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH;AACA;;AAEA;AACA;;AAEA;AACA,6E;;;;;;;;;;;AChBA;AACA;AACA,mBAAmB,sBAAsB;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,6E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnBA;AACA;AAEA,MAAM;AAAEA;AAAF,IAAmBC,EAAE,CAACC,KAA5B;AACA;AACA;AAEA;;AAEA,MAAMC,cAAN,SAA6BC,4DAA7B,CAAuC;AAEnCC,aAAW,CAAEC,KAAF,EAAU;AACjB,UAAOA,KAAP;;AADiB,kGAsCTC,QAAF,IAAgB;AACtB,WAAKC,QAAL,CAAc;AACVC,cAAM,EAAEF;AADE,OAAd;AAGH,KA1CoB;;AAAA,qGA4CR,MAAM;AACf,WAAKG,OAAL,CAAc,KAAd;AACH,KA9CoB;;AAEjB,SAAKC,KAAL,GAAa;AACTF,YAAM,EAAE,IADC;AAETG,eAAS,EAAE,IAFF;AAGTC,sBAAgB,EAAE,CAHT;AAITC,4BAAsB,EAAE,CAJf;AAKTC,QAAE,EAAE,EALK;AAMTC,aAAO,EAAE,EANA;AAOTC,aAAO,EAAE,EAPA;AAQTC,mBAAa,EAAE,EARN;AASTC,aAAO,EAAE,EATA;AAUTC,iBAAW,EAAE,EAVJ;AAWTC,eAAS,EAAE,EAXF;AAYTC,cAAQ,EAAE,EAZD;AAaTC,oBAAc,EAAE;AAbP,KAAb;AAeH;;AAEDC,mBAAiB,GAAG;AAChBC,+DAAQ,CAAE;AACNC,UAAI,EAAE,6BAA6B,KAAKpB,KAAL,CAAWqB,EAAxC,GAA6C,GAD7C;AAENC,YAAM,EAAE;AAFF,KAAF,CAAR,CAGIC,IAHJ,CAGYC,GAAF,IAAW;AACjB,WAAKtB,QAAL,CAAc,EACV,GAAGsB,GADO;AAEVlB,iBAAS,EAAE;AAFD,OAAd;AAMH,KAVD,EAUImB,KAAD,IAAW;AACV,WAAKvB,QAAL,CAAe;AACZI,iBAAS,EAAE;AADC,OAAf;AAGAoB,WAAK,CAAE,kDAAkDD,KAAK,CAACd,OAAxD,GAAkE,GAAlE,GAAwEc,KAAK,CAACE,IAA9E,GAAoF,GAAtF,CAAL;AACH,KAfD;AAgBH;;AAYDC,QAAM,GAAG;AACL,UAAM;AAAEP,QAAF;AAAMZ,QAAN;AAAUC;AAAV,QAAsB,KAAKV,KAAjC;AAEA,UAAM6B,KAAK,GAAGC,OAAO,CAAEC,0DAAE,CAAC,WAAD,EAAc,eAAd,CAAJ,EAAoCrB,OAApC,CAArB;AACA,UAAMsB,IAAI,GAAG,WAAb;AACA,UAAMC,aAAa,GAAG,IAAtB;AACA,UAAMC,YAAY,GAAG,IAArB;AACA,UAAMC,gBAAgB,GAAG,IAAzB;AACA,UAAMC,yBAAyB,GAAG,IAAlC;AAEA,UAAMC,aAAa,GAAGL,IAAI,GAAG,yEAAC,8DAAD;AAAU,UAAI,EAAGA;AAAjB,MAAH,GAAgC,IAA1D;AAEA,UAAMM,UAAU,GAAG;AACfN,UAAI,EAAEK,aADS;AAEfH,kBAFe;AAGfD,mBAHe;AAIfE,sBAJe;AAKfC,+BALe;AAMfP;AANe,KAAnB;AASA,QAAIU,SAAJ;;AACA,QAAK,KAAKlC,KAAL,CAAWC,SAAhB,EAA4B;AACxBiC,eAAS,GACL,yEAAC,6DAAD;AAAS,aAAK,EAAC,MAAf;AAAsB,YAAI,EAAC;AAA3B,QADJ;AAGH,KAJD,MAIO;AACH,YAAMC,kBAAkB,GAAGC,6CAAM,CAACC,GAAP,CAAY,KAAKrC,KAAL,CAAWU,SAAvB,EAAmC4B,KAAnC,EAA3B;AAEA,UAAIC,mBAAJ;;AACA,UAAK,KAAKvC,KAAL,CAAWW,QAAX,CAAoB6B,MAAzB,EAAkC;AAC9BD,2BAAmB,GACf,yEAAC,8DAAD,QACI,qFACM,KAAKvC,KAAL,CAAWW,QAAX,CAAoB8B,GAApB,CAAyB9B,QAAQ,IAAI;AAC/B,cAAI+B,iBAAiB,GAAGN,6CAAM,CAACC,GAAP,CAAY1B,QAAQ,CAACD,SAArB,EAAiC4B,KAAjC,EAAxB;AACA,iBACI,qFACMb,OAAO,CAAEC,0DAAE,CAAE,qBAAF,EAAyB,eAAzB,CAAJ,EAA+CgB,iBAAiB,CAACC,MAAlB,CAA0B,+BAA1B,IAA8D,IAA9D,GAAqED,iBAAiB,CAACE,OAAlB,EAArE,GAAmG,GAAlJ,EAAuJjC,QAAQ,CAACkC,UAAhK,CADb,CADJ;AAKH,SAPH,CADN,CADJ,CADJ;AAcH,OAfD,MAeO;AACHN,2BAAmB,GAAGb,0DAAE,CAAE,KAAF,EAAS,eAAT,CAAxB;AACH;;AAED,UAAI1B,KAAK,GAAG,KAAKA,KAAjB;AACA,UAAI8C,WAAW,GAAGzD,YAAY,CAAE,sCAAF,EAA0C,IAA1C,EAAgDW,KAAhD,CAA9B;AAEAkC,eAAS,GACL,yEAAC,2DAAD,QACI,yEAAC,2DAAD;AAAO,cAAM,EAAGR,0DAAE,CAAE,6BAAF,EAAiC,eAAjC;AAAlB,SACI,yEAAC,+DAAD;AAAW,aAAK,EAAG,MAAMD,OAAO,CAAEsB,0DAAE,CAAE,cAAF,EAAkB,eAAlB,EAAmCC,QAAQ,CAAE,KAAKhD,KAAL,CAAWE,gBAAb,CAA3C,EAA4E,eAA5E,CAAJ,EAAmG,KAAKF,KAAL,CAAWE,gBAA9G,CAAhC;AAAmK,mBAAW,EAAG,KAAKF,KAAL,CAAWW,QAAX,CAAoB6B,MAApB,GAA6B,IAA7B,GAAoC;AAArN,SACMD,mBADN,CADJ,EAIMO,WAJN,CADJ,EAOI,oFAPJ,EAQI,yEAAC,2DAAD;AAAO,cAAM,EAAC;AAAd,SACI,yEAAC,+DAAD;AAAW,aAAK,EAAG,IAAnB;AAA0B,mBAAW,EAAG;AAAxC,SACI,yEAAC,8DAAD,QAAY,KAAK9C,KAAL,CAAWI,EAAvB,CADJ,CADJ,EAII,yEAAC,+DAAD;AAAW,aAAK,EAAG,gBAAnB;AAAsC,mBAAW,EAAG;AAApD,SACI,yEAAC,8DAAD,QAAY+B,kBAAkB,CAACQ,MAAnB,CAA2B,+BAA3B,CAAZ,QAA8ER,kBAAkB,CAACS,OAAnB,EAA9E,MADJ,CAJJ,EAOM,KAAK5C,KAAL,CAAWQ,OAAX,IACU,yEAAC,+DAAD;AAAW,aAAK,EAAG,SAAnB;AAA+B,mBAAW,EAAG;AAA7C,SACI,yEAAC,8DAAD,QAAc,KAAKR,KAAL,CAAWQ,OAAzB,CADJ,CARhB,EAYM,KAAKR,KAAL,CAAWS,WAAX,IACM,yEAAC,+DAAD;AAAW,aAAK,EAAG,aAAnB;AAAmC,mBAAW,EAAG;AAAjD,SACI,yEAAC,8DAAD,QACM,KAAKT,KAAL,CAAWS,WAAX,CAAuBwC,KAAvB,CAA6B,MAA7B,EAAqCR,GAArC,CAA0CS,UAAU,IAAI;AACtD,YAAIC,cAAc,GAAGC,aAAa,CAACC,WAAd,GAA4BH,UAAjD;AACA,YAAII,gBAAgB,GAAGJ,UAAU,CAACD,KAAX,CAAiB,GAAjB,CAAvB;AACA,eACQ,yEAAC,2DAAD,QACI;AAAG,cAAI,EAAEE,cAAT;AAAyB,gBAAM,EAAC;AAAhC,WAA0CG,gBAAgB,CAACA,gBAAgB,CAACd,MAAjB,GAA0B,CAA3B,CAA1D,CADJ,CADR;AAKH,OARC,CADN,CADJ,CAbZ,EA2BI,yEAAC,+DAAD;AAAW,aAAK,EAAG,SAAnB;AAA+B,mBAAW,EAAG;AAA7C,SACI,yEAAC,8DAAD,QACI;AAAK,+BAAuB,EAAE;AAACe,gBAAM,EAAE,KAAKvD,KAAL,CAAWM;AAApB;AAA9B,QADJ,CADJ,CA3BJ,CARJ,EAyCI,oFAzCJ,EA0CI,yEAAC,4DAAD;AAAQ,qBAAa,MAArB;AAAsB,eAAO,EAAG,IAAhC;AAAuC,eAAO,EAAG,KAAKkD;AAAtD,SACM9B,0DAAE,CAAC,OAAD,EAAU,eAAV,CADR,CA1CJ,CADJ;AAgDH;;AAED,WACI,yEAAC,2DAAD,QAEM,KAAK1B,KAAL,CAAWF,MAAX,IACF,yEAAC,2DAAD,4EAAYmC,UAAZ;AAAyB,WAAK,EAAE;AAAEwB,gBAAQ,EAAE;AAAZ,OAAhC;AAAqD,oBAAc,EAAG,KAAKD;AAA3E,QACMtB,SADN,CAHJ,CADJ;AAUH;;AAlKkC;;AAsKvCwB,MAAM,CAACC,YAAP,GAAsB,SAASA,YAAT,CAAuB3C,EAAvB,EAA2BX,OAAO,GAAG,EAArC,EAA0CD,EAAE,GAAG,EAA/C,EAAoD;AACtE,MAAIwD,SAAS,GAAG;AACZ5C,MADY;AAEZX,WAFY;AAGZD;AAHY,GAAhB;AAMA,QAAMyD,IAAI,GAAGC,QAAQ,CAACC,cAAT,CAAyB,iCAAzB,CAAb;AAEAC,mFAAsB,CAAEH,IAAF,CAAtB;AACAtC,mEAAM,CAAE,yEAAC,cAAD,EAAoBqC,SAApB,CAAF,EAAqCC,IAArC,CAAN;AAEA,SAAO,KAAP;AACH,CAbD,C;;;;;;;;;;;AChLA,aAAa,2CAA2C,EAAE,I;;;;;;;;;;;ACA1D,aAAa,6CAA6C,EAAE,I;;;;;;;;;;;ACA5D,aAAa,0CAA0C,EAAE,I;;;;;;;;;;;ACAzD,aAAa,uCAAuC,EAAE,I;;;;;;;;;;;ACAtD,aAAa,mCAAmC,EAAE,I","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":";;;;;;;;;;AAAA,0C;;;;;;;;;;ACAA,4C;;;;;;;;;;ACAA,yC;;;;;;;;;;ACAA,sC;;;;;;;;;;ACAA,kC;;;;;;;;;;ACAA,2C;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;;;;WCtBA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA,E;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D,E;;;;;;;;;;;;;;;;;;;;;;;ACL6F;AACqB;AAElH,MAAM;EAAEY;AAAa,CAAC,GAAGC,EAAE,CAACC,KAAK;AACW;AACM;AAEtB;AAAA;AAE5B,MAAMU,cAAc,SAASrB,yDAAS,CAAC;EAEnCsB,WAAWA,CAAEC,KAAK,EAAG;IACjB,KAAK,CAAEA,KAAM,CAAC;IACd,IAAI,CAACC,KAAK,GAAG;MACTC,MAAM,EAAE,IAAI;MACZC,SAAS,EAAE,IAAI;MACfC,gBAAgB,EAAE,CAAC;MACnBC,sBAAsB,EAAE,CAAC;MACzBC,EAAE,EAAE,EAAE;MACNC,OAAO,EAAE,EAAE;MACXC,OAAO,EAAE,EAAE;MACXC,aAAa,EAAE,EAAE;MACjBC,OAAO,EAAE,EAAE;MACXC,WAAW,EAAE,EAAE;MACfC,SAAS,EAAE,EAAE;MACbC,QAAQ,EAAE,EAAE;MACZC,cAAc,EAAE;IACpB,CAAC;EACL;EAEAC,iBAAiBA,CAAA,EAAG;IAChB1B,2DAAQ,CAAE;MACN2B,IAAI,EAAE,0BAA0B,GAAG,IAAI,CAAChB,KAAK,CAACiB,EAAE,GAAG,GAAG;MACtDC,MAAM,EAAE;IACZ,CAAE,CAAC,CAACC,IAAI,CAAIC,GAAG,IAAM;MACjB,IAAI,CAACC,QAAQ,CAAC;QACV,GAAGD,GAAG;QACNjB,SAAS,EAAE;MACf,CAAC,CAAC;IAGN,CAAC,EAAGmB,KAAK,IAAK;MACV,IAAI,CAACD,QAAQ,CAAE;QACZlB,SAAS,EAAE;MACd,CAAE,CAAC;MACHoB,KAAK,CAAE,+CAA+C,GAAGD,KAAK,CAACd,OAAO,GAAG,GAAG,GAAGc,KAAK,CAACE,IAAI,GAAE,GAAI,CAAC;IACpG,CAAE,CAAC;EACP;EAEAC,OAAO,GAAKC,QAAQ,IAAM;IACtB,IAAI,CAACL,QAAQ,CAAC;MACVnB,MAAM,EAAEwB;IACZ,CAAC,CAAC;EACN,CAAC;EAEDC,UAAU,GAAGA,CAAA,KAAM;IACf,IAAI,CAACF,OAAO,CAAE,KAAM,CAAC;EACzB,CAAC;EAEDG,MAAMA,CAAA,EAAG;IACL,MAAM;MAAEX,EAAE;MAAEX,EAAE;MAAEC;IAAQ,CAAC,GAAG,IAAI,CAACP,KAAK;IAEtC,MAAM6B,KAAK,GAAGrC,wDAAO,CAAEF,mDAAE,CAAC,WAAW,EAAE,eAAe,CAAC,EAAEiB,OAAQ,CAAC;IAClE,MAAMuB,IAAI,GAAG,WAAW;IACxB,MAAMC,aAAa,GAAG,IAAI;IAC1B,MAAMC,YAAY,GAAG,IAAI;IACzB,MAAMC,gBAAgB,GAAG,IAAI;IAC7B,MAAMC,yBAAyB,GAAG,IAAI;IAEtC,MAAMC,aAAa,GAAGL,IAAI,gBAAGnC,sDAAA,CAACf,2DAAQ;MAACkD,IAAI,EAAGA;IAAM,CAAE,CAAC,GAAG,IAAI;IAE9D,MAAMM,UAAU,GAAG;MACfN,IAAI,EAAEK,aAAa;MACnBH,YAAY;MACZD,aAAa;MACbE,gBAAgB;MAChBC,yBAAyB;MACzBL;IACJ,CAAC;IAED,IAAIQ,SAAS;IACb,IAAK,IAAI,CAACpC,KAAK,CAACE,SAAS,EAAG;MACxBkC,SAAS,gBACL1C,sDAAA,CAACV,0DAAO;QAACqD,KAAK,EAAC,MAAM;QAACC,IAAI,EAAC;MAAK,CAAE,CACrC;IACL,CAAC,MAAM;MACH,MAAMC,kBAAkB,GAAG/C,iDAAU,CAAE,IAAI,CAACQ,KAAK,CAACW,SAAU,CAAC,CAAC8B,KAAK,CAAC,CAAC;MAErE,IAAIC,mBAAmB;MACvB,IAAK,IAAI,CAAC1C,KAAK,CAACY,QAAQ,CAAC+B,MAAM,EAAG;QAC9BD,mBAAmB,gBACfhD,sDAAA,CAACZ,2DAAQ;UAAA8D,QAAA,eACLlD,sDAAA;YAAAkD,QAAA,EAEM,IAAI,CAAC5C,KAAK,CAACY,QAAQ,CAACiC,GAAG,CAAE,CAACjC,QAAQ,EAAEkC,KAAK,KAAK;cACxC,IAAIC,iBAAiB,GAAGvD,iDAAU,CAAEoB,QAAQ,CAACD,SAAU,CAAC,CAAC8B,KAAK,CAAC,CAAC;cAChE,oBACI/C,sDAAA;gBAAAkD,QAAA,EACMrD,wDAAO,CAAEF,mDAAE,CAAE,qBAAqB,EAAE,eAAe,CAAC,EAAE0D,iBAAiB,CAACC,MAAM,CAAE,+BAAgC,CAAC,GAAG,IAAI,GAAGD,iBAAiB,CAACE,OAAO,CAAC,CAAC,GAAG,GAAG,EAAErC,QAAQ,CAACsC,UAAW;cAAC,GADhLJ,KAEL,CAAC;YAEb,CACJ;UAAC,CACD;QAAC,CACC,CAAG;MACrB,CAAC,MAAM;QACHJ,mBAAmB,GAAGrD,mDAAE,CAAE,KAAK,EAAE,eAAgB,CAAC;MACtD;MAEA,IAAIW,KAAK,GAAG,IAAI,CAACA,KAAK;MACtB,IAAImD,WAAW,GAAGlE,YAAY,CAAE,sCAAsC,EAAE,IAAI,EAAEe,KAAM,CAAC;MAErFoC,SAAS,gBACLxC,uDAAA,CAACrB,wDAAQ;QAAAqE,QAAA,gBACLhD,uDAAA,CAACf,wDAAK;UAACuE,MAAM,EAAG/D,mDAAE,CAAE,6BAA6B,EAAE,eAAe,CAAG;UAAAuD,QAAA,gBACjElD,sDAAA,CAACX,4DAAS;YAAC6C,KAAK,EAAG,GAAG,GAAGrC,wDAAO,CAAED,mDAAE,CAAE,cAAc,EAAE,eAAe,EAAE+D,QAAQ,CAAE,IAAI,CAACrD,KAAK,CAACG,gBAAiB,CAAC,EAAE,eAAgB,CAAC,EAAE,IAAI,CAACH,KAAK,CAACG,gBAAiB,CAAG;YAACmD,WAAW,EAAG,IAAI,CAACtD,KAAK,CAACY,QAAQ,CAAC+B,MAAM,GAAG,IAAI,GAAG,KAAO;YAAAC,QAAA,EACtNF;UAAmB,CACd,CAAC,EACVS,WAAW;QAAA,CACV,CAAC,eACRzD,sDAAA,SAAK,CAAC,eACNE,uDAAA,CAACf,wDAAK;UAACuE,MAAM,EAAC,YAAY;UAAAR,QAAA,gBACtBlD,sDAAA,CAACX,4DAAS;YAAC6C,KAAK,EAAG,IAAM;YAAC0B,WAAW,EAAG,IAAM;YAAAV,QAAA,eAC1ClD,sDAAA,CAACZ,2DAAQ;cAAA8D,QAAA,EAAG,IAAI,CAAC5C,KAAK,CAACK;YAAE,CAAY;UAAC,CAC/B,CAAC,eACZX,sDAAA,CAACX,4DAAS;YAAC6C,KAAK,EAAG,gBAAkB;YAAC0B,WAAW,EAAG,IAAM;YAAAV,QAAA,eACtDhD,uDAAA,CAACd,2DAAQ;cAAA8D,QAAA,GAAGL,kBAAkB,CAACS,MAAM,CAAE,+BAAgC,CAAC,EAAE,IAAE,EAAET,kBAAkB,CAACU,OAAO,CAAC,CAAC,EAAE,GAAC;YAAA,CAAU;UAAC,CACjH,CAAC,EACV,IAAI,CAACjD,KAAK,CAACS,OAAO,iBACRf,sDAAA,CAACX,4DAAS;YAAC6C,KAAK,EAAG,SAAW;YAAC0B,WAAW,EAAG,IAAM;YAAAV,QAAA,eAC/ClD,sDAAA,CAACZ,2DAAQ;cAAA8D,QAAA,EAAK,IAAI,CAAC5C,KAAK,CAACS;YAAO,CAAc;UAAC,CACxC,CAAC,EAEtB,IAAI,CAACT,KAAK,CAACU,WAAW,iBAChBhB,sDAAA,CAACX,4DAAS;YAAC6C,KAAK,EAAG,aAAe;YAAC0B,WAAW,EAAG,IAAM;YAAAV,QAAA,eACnDlD,sDAAA,CAACZ,2DAAQ;cAAA8D,QAAA,EACH,IAAI,CAAC5C,KAAK,CAACU,WAAW,CAAC6C,KAAK,CAAC,MAAM,CAAC,CAACV,GAAG,CAAE,CAACW,UAAU,EAAEV,KAAK,KAAK;gBAC/D,IAAIW,cAAc,GAAGC,aAAa,CAACC,WAAW,GAAGH,UAAU;gBAC3D,IAAII,gBAAgB,GAAGJ,UAAU,CAACD,KAAK,CAAC,GAAG,CAAC;gBAC5C,oBACQ7D,sDAAA,CAACnB,wDAAQ;kBAAAqE,QAAA,eACLlD,sDAAA;oBAAGmE,IAAI,EAAEJ,cAAe;oBAACK,MAAM,EAAC,QAAQ;oBAAAlB,QAAA,EAAEgB,gBAAgB,CAACA,gBAAgB,CAACjB,MAAM,GAAG,CAAC;kBAAC,CAAI;gBAAC,GADjFG,KAEL,CAAC;cAEvB,CAAC;YAAC,CACI;UAAC,CACJ,CAAC,eAEpBpD,sDAAA,CAACX,4DAAS;YAAC6C,KAAK,EAAG,SAAW;YAAC0B,WAAW,EAAG,IAAM;YAAAV,QAAA,eAC/ClD,sDAAA,CAACZ,2DAAQ;cAAA8D,QAAA,eACLlD,sDAAA;gBAAKqE,uBAAuB,EAAG;kBAAEC,MAAM,EAAE,IAAI,CAAChE,KAAK,CAACO;gBAAQ;cAAG,CAAM;YAAC,CAChE;UAAC,CACJ,CAAC;QAAA,CACT,CAAC,eACRb,sDAAA,SAAK,CAAC,eACNA,sDAAA,CAAChB,yDAAM;UAACuF,aAAa;UAACC,OAAO,EAAG,IAAM;UAACC,OAAO,EAAG,IAAI,CAACzC,UAAY;UAAAkB,QAAA,EAC5DvD,mDAAE,CAAC,OAAO,EAAE,eAAgB;QAAC,CAC3B,CAAC;MAAA,CACH,CACb;IACL;IAEA,oBACIK,sDAAA,CAACnB,wDAAQ;MAAAqE,QAAA,EAEH,IAAI,CAAC5C,KAAK,CAACC,MAAM,iBACnBP,sDAAA,CAACd,wDAAK;QAAA,GAAMuD,UAAU;QAAGiC,KAAK,EAAE;UAAEC,QAAQ,EAAE;QAAM,CAAE;QAACC,cAAc,EAAG,IAAI,CAAC5C,UAAY;QAAAkB,QAAA,EACjFR;MAAS,CACR;IAAC,CAEF,CAAC;EAEnB;AACJ;AAGAmC,MAAM,CAACC,YAAY,GAAG,SAASA,YAAYA,CAAExD,EAAE,EAAEV,OAAO,GAAG,EAAE,EAAGD,EAAE,GAAG,EAAE,EAAG;EACtE,IAAIoE,SAAS,GAAG;IACZzD,EAAE;IACFV,OAAO;IACPD;EACJ,CAAC;EAED,MAAMqE,SAAS,GAAGC,QAAQ,CAACC,cAAc,CAAE,iCAAkC,CAAC;EAC9E,MAAMC,IAAI,GAAGxG,8DAAU,CAAEqG,SAAU,CAAC;;EAEpC;;EAEAG,IAAI,CAAClD,MAAM,cAAEjC,sDAAA,CAACG,cAAc;IAAA,GAAK4E;EAAS,CAAG,CAAE,CAAC;EAEhD,OAAO,KAAK;AAChB,CAAC,C","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
     11module.exports = window["wp"]["components"];
     12
     13/***/ }),
     14
     15/***/ "@wordpress/i18n":
     16/*!******************************!*\
     17  !*** external ["wp","i18n"] ***!
     18  \******************************/
     19/***/ ((module) => {
     20
     21module.exports = window["wp"]["i18n"];
     22
     23/***/ }),
     24
     25/***/ "moment":
     26/*!*************************!*\
     27  !*** external "moment" ***!
     28  \*************************/
     29/***/ ((module) => {
     30
     31module.exports = window["moment"];
     32
     33/***/ }),
     34
     35/***/ "react/jsx-runtime":
     36/*!**********************************!*\
     37  !*** external "ReactJSXRuntime" ***!
     38  \**********************************/
     39/***/ ((module) => {
     40
     41module.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/************************************************************************/
     113var __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
     130const {
     131  addFilter
     132} = wp.hooks;
     133
     134
     135addFilter('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  
    2020  "license": "ISC",
    2121  "devDependencies": {
    22     "@wordpress/scripts": "^16.1.1"
     22    "@wordpress/scripts": "^31.1.0"
    2323  },
    2424  "dependencies": {}
  • email-tracker/trunk/assets/src/index.js

    r2670982 r3416646  
    11
    2 import { render, unmountComponentAtNode, Fragment, Component } from '@wordpress/element';
     2import { createRoot, unmountComponentAtNode, Fragment, Component } from '@wordpress/element';
    33import { ButtonGroup, Button, Dashicon, Modal, Panel, PanelRow, PanelBody, Spinner } from '@wordpress/components';
    44
    55const { applyFilters } = wp.hooks;
    66import apiFetch from '@wordpress/api-fetch';
    7 import { __, _n } from '@wordpress/i18n';
     7import { __, _n, sprintf } from '@wordpress/i18n';
    88
    99import moment from 'moment';
     
    3939                isLoading: false,
    4040            });
    41            
    42            
     41
     42
    4343        }, (error) => {
    4444            this.setState( {
     
    9393                    <PanelRow>
    9494                        <ol>
    95                             { this.state.read_log.map( read_log => {
     95
     96                            { this.state.read_log.map( (read_log, index) => {
    9697                                    let read_local_moment = moment.utc( read_log.date_time ).local();
    9798                                    return (
    98                                         <li>
     99                                        <li key={index}>
    99100                                            { 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 )}
    100101                                        </li>
    101102                                        )
    102103                                }
    103                             )}
     104                            ) }
    104105                        </ol>
    105106                    </PanelRow> );
     
    107108                read_log_panel_body = __( 'N/A', 'email-tracker' );
    108109            }
    109            
     110
    110111            let state = this.state;
    111112            let extra_panel = applyFilters( 'email-tracker-view-email-extra-panel', null, state );
    112            
     113
    113114            modalBody = (
    114115                <Fragment>
     
    127128                            <PanelRow>{ moment_local_email.format( 'MMMM Do YYYY, dddd, h:mm:ss a' ) } ({ moment_local_email.fromNow() })</PanelRow>
    128129                        </PanelBody>
    129                         { this.state.headers && 
     130                        { this.state.headers &&
    130131                                    <PanelBody title={ "Headers" } initialOpen={ true }>
    131132                                        <PanelRow>{ ( this.state.headers ) }</PanelRow>
    132133                                    </PanelBody>
    133134                        }
    134                         { this.state.attachments && 
     135                        { this.state.attachments &&
    135136                                <PanelBody title={ "Attachments" } initialOpen={ true }>
    136137                                    <PanelRow>
    137                                         { this.state.attachments.split(",\\n").map( attachment => {
     138                                        { this.state.attachments.split(",\\n").map( (attachment, index) => {
    138139                                            let attachment_url = email_tracker.content_url + attachment;
    139140                                            let attachment_split = attachment.split("/");
    140141                                            return (
    141                                                     <Fragment>
     142                                                    <Fragment key={index}>
    142143                                                        <a href={attachment_url} target="_blank">{attachment_split[attachment_split.length - 1]}</a>
    143144                                                    </Fragment>
     
    149150                        <PanelBody title={ "Message" } initialOpen={ true }>
    150151                            <PanelRow>
    151                                 <div dangerouslySetInnerHTML={{__html: this.state.message}}></div>
     152                                <div dangerouslySetInnerHTML={ { __html: this.state.message } }></div>
    152153                            </PanelRow>
    153154                        </PanelBody>
     
    163164        return (
    164165            <Fragment>
    165                
    166                 { this.state.isOpen && 
     166
     167                { this.state.isOpen &&
    167168                <Modal { ...modalProps } style={{ minWidth: '75%' }} onRequestClose={ this.closeModal }>
    168169                    { modalBody }
     
    182183    };
    183184
    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 );
    185187
    186     unmountComponentAtNode( root );
    187     render( <EmailModalView {...passProps} />, root );
     188    // root.unmount(); // Unmount the component from the root
     189
     190    root.render( <EmailModalView {...passProps} /> );
    188191
    189192    return false;
  • email-tracker/trunk/assets/src/pro/index.js

    r2670982 r3416646  
    1 import { __, _n } from '@wordpress/i18n';
    21import { PanelRow, PanelBody } from '@wordpress/components';
    3 
     2import { __, _n, sprintf } from '@wordpress/i18n';
    43
    54const { addFilter } = wp.hooks;
  • email-tracker/trunk/composer.json

    r3340406 r3416646  
    1010    ],
    1111    "require": {
    12         "soundasleep/html2text": "^2.0"
     12        "soundasleep/html2text": "^2.0",
     13        "freemius/wordpress-sdk": "^2.13"
    1314    }
    1415}
  • email-tracker/trunk/composer.lock

    r2670982 r3416646  
    55        "This file is @generated automatically"
    66    ],
    7     "content-hash": "a32ca914ceef26f719b7b87c0c48b60e",
     7    "content-hash": "c1a7225e1319395053252465187b61ea",
    88    "packages": [
    99        {
     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        {
    1063            "name": "soundasleep/html2text",
    11             "version": "1.1.0",
     64            "version": "2.1.0",
    1265            "source": {
    1366                "type": "git",
    1467                "url": "https://github.com/soundasleep/html2text.git",
    15                 "reference": "3243a7107878a61685d2eccf99918d6479e039fc"
     68                "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3"
    1669            },
    1770            "dist": {
    1871                "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",
    2174                "shasum": ""
    2275            },
     
    2477                "ext-dom": "*",
    2578                "ext-libxml": "*",
    26                 "php": ">=7.0"
     79                "php": "^7.3|^8.0"
    2780            },
    2881            "require-dev": {
    29                 "phpunit/phpunit": "~7.0",
    30                 "soundasleep/component-tests": "~0.2"
     82                "phpstan/phpstan": "^1.9",
     83                "phpunit/phpunit": "^7.0|^8.0|^9.0"
    3184            },
    3285            "type": "library",
     
    58111                "email": "support@jevon.org",
    59112                "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"
    61114            },
    62             "time": "2019-02-15T01:44:54+00:00"
     115            "time": "2023-01-06T09:28:15+00:00"
    63116        }
    64117    ],
     
    66119    "aliases": [],
    67120    "minimum-stability": "stable",
    68     "stability-flags": [],
     121    "stability-flags": {},
    69122    "prefer-stable": false,
    70123    "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"
    74127}
  • email-tracker/trunk/email-tracker-main.php

    r3344738 r3416646  
    22
    33// Autoloading Vendor
    4 $autoloader = plugin_dir_path( EMTR_FILE ) . '/vendor/autoload.php';
     4$emtr_autoloader = plugin_dir_path( EMTR_FILE ) . '/vendor/autoload.php';
    55// When WordPress is loaded as composer dependecy, There will not be __DIR__/vendor/autoload.php pressent.
    66// so we need to check
    7 if ( is_readable( $autoloader ) ) {
    8     require $autoloader;
    9 }
    10 
    11 
     7if ( is_readable( $emtr_autoloader ) ) {
     8    require $emtr_autoloader;
     9}
    1210require_once plugin_dir_path( EMTR_FILE ) . '/defines.php';
    1311require_once plugin_dir_path( EMTR_FILE ) . '/src/class-email-tracker-invoker.php';
    1412\PrashantWP\Email_Tracker\Email_Tracker_Invoker::register();
    15 
    1613/*
    1714 * includes  all functions which required by plugin
    1815 */
    1916if ( 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';
    2421}
    2522/**
     
    2724 */
    2825define( 'EMTR_DB_VERSION', '1.2.1' );
    29 define( 'EMTR_VERSION', '5.3.14' );
     26define( 'EMTR_VERSION', '5.3.16' );
    3027/*
    3128* Upgrade Script
    3229*/
    3330if ( 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}
    3733/**
    3834 * This function and hook set default value of setting
     
    4036 */
    4137function 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
     62function 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();
    15283}
    15384
    15485register_activation_hook( EMTR_BASE_FILE_PATH, 'emtr_plugin_activate' );
    155 
    15686function emtr_uninstall_cleanup() {
    157     require_once EMTR_PLUGIN_PATH . '/emtr-uninstall.php';
     87    require_once EMTR_PLUGIN_PATH . '/emtr-uninstall.php';
    15888}
    15989
    16090emtr()->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'] );
     91function 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'] );
    176108        $orig_email['message'] = nl2br( $orig_email['message'] );
    177109    }
    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;
    293158}
    294159
    295160add_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 
     161function emtr_extract_email_field(  $email_field  ) {
     162    return ( is_array( $email_field ) ? implode( ', ', $email_field ) : $email_field );
     163}
     164
     165function 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
     200add_filter(
     201    'pre_wp_mail',
     202    'emtr_pre_wp_mail',
     203    10,
     204    2
     205);
    340206/**
    341207 * Filter the mail content type.
    342208 */
    343209add_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;
     210function 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
     221function 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;
    361226}
    362227
    363228add_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' );
     229function 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
     236add_filter( 'query_vars', 'emtr_query_vars' );
    372237add_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     }
     238function 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    }
    404245}
    405246
     
    413254*/
    414255class 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
    480318$Emtr_Mailer = new Emtr_Mailer();
    481319$Emtr_Mailer->add_hooks();
  • email-tracker/trunk/email-tracker.php

    r3344738 r3416646  
    44 * Plugin URI:  https://wordpress.org/plugins/email-tracker/
    55 * 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
    1110 * Text Domain: email-tracker
    1211 * Domain Path: /languages
     
    2827 * along with Email Tracker. If not, see <http://www.gnu.org/licenses/>.
    2928 *
    30  * @fs_premium_only /src/admin/settings/
    31  */
     29  */
    3230
    3331namespace PrashantWP\Email_Tracker;
     
    3836
    3937if ( function_exists( 'emtr' ) ) {
    40     emtr()->set_basename( true, __FILE__ );
     38    emtr()->set_basename( false, __FILE__ );
    4139} else {
    4240    // 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
    22/**
    33 * To delete plugin
     
    2222     */
    2323    $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};" );
    2547
    2648    /**
     
    2850     */
    2951    $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};" );
    4954
    5055    /**
    5156     * Delete email list per page screen option value
    5257     */
    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'" );
    5460
    5561    delete_option( \PrashantWP\Email_Tracker\Util::get_factory()->get( '\PrashantWP\Email_Tracker\Options' )->get_option_name() );
     
    6268}
    6369
    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;
     71foreach ($emtr_all_roles as $emtr_role_key => $role_val ) {
     72    $ret = wp_roles()->remove_cap( $emtr_role_key, EMTR_MANAGE_ALL_EMAILS_CAP );
    6773}
    6874
     
    7278    $old_blog = $wpdb->blogid;
    7379    // 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 );
    7581    foreach ( $blogids as $blog_id ) {
    7682        switch_to_blog( $blog_id );
  • email-tracker/trunk/et-admin.php

    r2670982 r3416646  
    4545
    4646function emtr_render_compose_email() {
     47    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
    4748    if ( 'POST' == $_SERVER['REQUEST_METHOD'] && ! empty( $_POST['action'] ) && $_POST['action'] == 'emtr_send_mail' && wp_verify_nonce( $_POST['_wpnonce'], 'emtr_compose_email' ) ) {
    4849
    4950        if ( isset( $_POST['to'] ) ) {
    50             $to = sanitize_text_field( $_POST['to'] );
     51            $to = sanitize_text_field( wp_unslash( $_POST['to'] ) );
    5152        }
    5253        if ( isset( $_POST['subject'] ) ) {
    53             $subject = sanitize_text_field( $_POST['subject'] );
     54            $subject = sanitize_text_field( wp_unslash( $_POST['subject'] ) );
    5455        }
    5556        if ( isset( $_POST['message'] ) ) {
    5657            // message may be content of html tags
    57             $message = wp_kses_post( $_POST['message'] );
     58            $message = wp_kses_post( wp_unslash( $_POST['message'] ) );
    5859        }
    5960
    6061        $arr_attachments = array();
    6162        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'] ) );
    6365            $arr_attachments_url = array_map( 'sanitize_text_field', $arr_attachments_url );
    6466            $arr_attachments     = array();
     
    173175        wp_enqueue_style( 'emtr_compose_email_css', plugins_url( 'css/compose_email.css', EMTR_BASE_FILE_PATH ), array(), '0.1', 'all' );
    174176        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 ) );
    176178    }
    177179}
     
    180182/* To resolve header already sent error */
    181183function 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.
    183185        &&
    184186        (
    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.
    186188            ||
    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.
    188190        )
    189191     ) {
  • 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, freemius
     1=== Email Tracker ==
     2Contributors: pmbaldha, nikunj8866, freemius
    33Tags: email, emails, email tracking, email log, email analytics
    4 Requires at least: 5.0
    5 Tested up to: 6.8
    6 Stable tag: 5.3.15
     4Requires at least: 5.6.0
     5Tested up to: 6.9
     6Stable tag: 5.3.16
    77License: GPLv3 or later
    88License URI: https://www.gnu.org/licenses/gpl-3.0.html
     
    158158**And many more!** Email Tracker works with any WordPress plugin that uses the standard wp_mail() function to send emails.
    159159
     160= SMTP & Email Delivery Plugins: =
     161Email 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: =
     175Track 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
    160195= Credits =
    161196
     
    173208* email tracker (incorrect)
    174209* Email traker (incorrect)
     210* Email email track (incorrect)
    175211* Email tracer (incorrect)
    176212* Mail Tracker (incorrect)
     
    182218* Mail traker (incorrect)
    183219* Mail tracer (incorrect)
     220* Email tracer (incorrect)
     221* Trace email (incorrect)
     222* Trace mail (incorrect)
     223* Trace emails (incorrect)
     224* Trace mails (incorrect)
     225
    184226
    185227== Installation ==
     
    380422
    381423== 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.
    382433
    383434= 5.3.15, August 15, 2025 =
  • email-tracker/trunk/src/admin/class-email-tracker-admin.php

    r3344738 r3416646  
    11<?php
     2
    23namespace PrashantWP\Email_Tracker\Admin;
    34
    4 if ( ! defined( 'ABSPATH' ) ) {
    5     exit;
     5if ( !defined( 'ABSPATH' ) ) {
     6    exit;
    67}
    7 
    88use Exception;
    99final class Email_Tracker_Admin extends \PrashantWP\Email_Tracker\Base {
    10 
    1110    /**
    12     * Self class instance
    13     *
    14     * @var object
    15     */
    16     private static $instance;
     11    * Self class instance
     12    *
     13    * @var object
     14    */
     15    private static $instance;
    1716
    1817    public function __construct() {
     
    2120
    2221    public static function register() {
    23         if ( ! isset( self::$instance ) ) {
     22        if ( !isset( self::$instance ) ) {
    2423            self::$instance = new self();
    25 
    2624            self::$instance->set_up_email_list();
    27             if ( emtr()->is__premium_only() ) {
    28                 self::$instance->set_up_settings__premium_only();
    29             }
    3025        }
    3126    }
    3227
    3328    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();
    3730    }
    3831
    39     public function set_up_settings__premium_only() {
    40         ( new Settings\Setup() )->init();
    41     }
    4232}
  • email-tracker/trunk/src/admin/email-list/class-setup.php

    r3344738 r3416646  
    11<?php
     2
    23namespace PrashantWP\Email_Tracker\Admin\Email_List;
    34
    4 if ( ! defined( 'ABSPATH' ) ) {
    5     exit;
     5if ( !defined( 'ABSPATH' ) ) {
     6    exit;
    67}
    7 
    8 
    98use PrashantWP\Email_Tracker\Util;
    10 
    119class Setup extends \PrashantWP\Email_Tracker\Base {
    12 
    1310    private $menu_slug;
     11
    1412    private $hook_suffix;
    1513
     
    2119    public function init() {
    2220        $this->hook();
    23        
    2421        $this->menu_page();
    2522        $this->help_tabs();
     
    2825
    2926    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') );
    4635    }
    4736
     
    5544
    5645    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        } );
    6857    }
    6958
     
    7362
    7463    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() ) ) {
    7665            $this->set_up_capability_to_administrator();
    7766        }
     
    8271    }
    8372
    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 ) {
    86125            return;
    87126        }
    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 scripts
    183      */
    184     public function admin_enqueue_scripts( $hook_suffix ) {
    185         // bail if email tracker admin page doesn't
    186         if ( $this->get_hook_suffix() !== $hook_suffix ) {
    187             return;
    188         }
    189 
    190127        $asset_path = plugin_dir_path( EMTR_FILE ) . 'assets/build/';
    191128        $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        ) );
    208140        wp_enqueue_style( 'wp-components' );
    209 
    210141        if ( file_exists( $asset_path . 'index.css' ) ) {
    211142            wp_enqueue_style(
     
    213144                $asset_url . 'index.css',
    214145                array(),
    215                 ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? time() : '1.0.1',
     146                ( defined( 'WP_DEBUG' ) && WP_DEBUG ? time() : '1.0.1' ),
    216147                'all'
    217148            );
    218149        }
     150        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- the full plugin name is used in hook name.
    219151        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    }
    264153
    265154    public function rest_api_init() {
    266155        // 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'),
    277162                ),
    278                 'permission_callback' => array( $this, 'rest_permission_check' ),
    279             )
    280         );
     163            ),
     164            'permission_callback' => array($this, 'rest_permission_check'),
     165        ) );
    281166    }
    282167
     
    291176    public function get_email_for_view( $request ) {
    292177        global $wpdb;
    293 
    294178        $ret_data = array();
    295179        $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
    301182        $email_row = $wpdb->get_row( $sql, ARRAY_A );
    302 
    303183        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!' ));
    305185        }
    306186        $pass_key_arr = array(
     
    313193            'date_time',
    314194            '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 ) {
    318198            $ret_data[$field] = $email_row[$field];
    319199        }
    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        }
    355216        $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 );
    358219        foreach ( $email_open_res as $row ) {
    359220            $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'],
    362223                'ip_address' => $row['ip_address'],
    363224            );
    364225        }
    365 
    366226        $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 );
    379229        foreach ( $email_link_res as $row ) {
    380230            $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'],
    384234                'ip_address' => $row['ip_address'],
    385235            );
    386236        }
    387 
    388237        return $ret_data;
    389238    }
  • email-tracker/trunk/src/admin/email-list/class-table.php

    r3344738 r3416646  
    11<?php
     2
    23/**
    34 * To list of all emails
    45 */
    56namespace PrashantWP\Email_Tracker\Admin\Email_List;
    6  
    7 if ( ! defined( 'ABSPATH' ) ) {
    8     exit;
     7
     8if ( !defined( 'ABSPATH' ) ) {
     9    exit;
    910}
    10 
    1111use PrashantWP\Email_Tracker\Util;
    12 
    13 if ( ! class_exists('\WP_List_Table' ) ) {
    14     require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
     12if ( !class_exists( '\\WP_List_Table' ) ) {
     13    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
    1514}
    16 
    1715/************************** CREATE A PACKAGE CLASS *****************************
    1816 *******************************************************************************
     
    2927 */
    3028class 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;
    3938
    4039    /** ************************************************************************
     
    4241     * use the parent reference to set some default configs.
    4342     ***************************************************************************/
    44     function __construct(){
     43    function __construct() {
    4544        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;
    5349        //Set parent defaults
    5450        parent::__construct( array(
    55             'singular'  => __('email', 'email-tracker'),     //singular name of the listed records
    56             'plural'    => __('emails', 'email-tracker'),    //plural name of the listed records
    57             'ajax'      => false        //does this table support ajax?
     51            'singular' => __( 'email', 'email-tracker' ),
     52            'plural'   => __( 'emails', 'email-tracker' ),
     53            'ajax'     => false,
    5854        ) );
    59        
    6055    }
    6156
    6257    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>';
    6459    }
    6560
     
    8580     * @return string Text or HTML to be placed inside the column <td>
    8681     **************************************************************************/
    87     function column_default($item, $column_name){
    88         switch($column_name){
     82    function column_default( $item, $column_name ) {
     83        switch ( $column_name ) {
    8984            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' ).'&nbsp;' . 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').'&nbsp;'.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' ) . '&nbsp;' . 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>';
    133109            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    }
    156128
    157129    /** ************************************************************************
     
    171143     * @return string Text to be placed inside the column <td> (movie title only)
    172144     **************************************************************************/
    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' );
    175147        $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>',
    178150        );
    179        
    180151        //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 )
    185160        );
    186161    }
    187 
    188162
    189163    /** ************************************************************************
     
    196170     * @return string Text to be placed inside the column <td> (movie title only)
    197171     **************************************************************************/
    198     function column_cb($item){
    199         return sprintf(
     172    function column_cb( $item ) {
     173        return sprintf( 
    200174            '<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    }
    206182
    207183    /** ************************************************************************
     
    218194     * @return array An associative array containing column information: 'slugs'=>'Visible Titles'
    219195     **************************************************************************/
    220     function get_columns(){
     196    function get_columns() {
    221197        $columns = array(
    222             'cb'          => '<input type="checkbox" />', //Render a checkbox instead of text
     198            'cb'          => '<input type="checkbox" />',
    223199            'to'          => esc_html__( 'To', 'email-tracker' ),
    224200            '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' ),
    231204        );
    232205        return $columns;
    233206    }
    234 
    235207
    236208    /** ************************************************************************
     
    250222    function get_sortable_columns() {
    251223        $sortable_columns = array(
    252             'to'     => array('to',false),     //true means it's already sorted
    253             '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),
    257229        );
    258230        return $sortable_columns;
    259231    }
    260 
    261232
    262233    /** ************************************************************************
     
    276247    function get_bulk_actions() {
    277248        $actions = array(
    278             'delete'    => esc_html__( 'Delete' , 'email-tracker' ),
     249            'delete' => esc_html__( 'Delete', 'email-tracker' ),
    279250        );
    280251        return $actions;
    281252    }
    282 
    283253
    284254    /** ************************************************************************
     
    292262        //Detect when a bulk action is being triggered...
    293263        if ( 'delete' === $this->current_action() ) {
    294             // Bulk Delete
     264            // Bulk Delete
    295265            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;
    308280            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'] ) );
    310284            } 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            }
    314288            $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        }
    337306    }
    338307
     
    353322     **************************************************************************/
    354323    function prepare_items() {
    355         global $wpdb; //This is used only if making any database queries
    356 
     324        global $wpdb;
     325        //This is used only if making any database queries
    357326        /**
    358327         * First, lets decide how many records per page to show
    359328         */
    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        }
    375341        /**
    376342         * REQUIRED. Now we need to define our column headers. This includes a complete
     
    383349        $hidden = array();
    384350        $sortable = $this->get_sortable_columns();
    385        
    386        
    387351        /**
    388352         * REQUIRED. Finally, we build an array to be used by the class for column
     
    392356         */
    393357        $this->_column_headers = array($columns, $hidden, $sortable);
    394        
    395        
    396358        /**
    397359         * Optional. You can handle your bulk actions however you see fit. In this
     
    399361         */
    400362        $this->process_bulk_action();
    401        
    402        
    403363        /**
    404364         * Instead of querying a database, we're going to fetch the example data
     
    410370         * be able to use your precisely-queried data immediately.
    411371         */
    412        
    413        
    414        
    415372        /**
    416373         * This checks for sorting input and sorts the data in our array accordingly.
     
    421378         * sorting technique would be unnecessary.
    422379         */
    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        }
    431389        $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') ) ) {
    435393                $order = $order_input;
    436394            }
    437395        }
    438 
    439396        /***********************************************************************
    440397         * ---------------------------------------------------------------------
     
    448405         * ---------------------------------------------------------------------
    449406         **********************************************************************/
    450 
    451407        /**
    452408         * REQUIRED for pagination. Let's figure out what page the user is currently
     
    455411         */
    456412        $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' ) ) {
    463418                die( 'Security issue' );
    464419            }
    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        }
    477435        /**
    478436         * REQUIRED for pagination. Let's check how many items are in our data array.
     
    481439         * in your own package classes.
    482440         */
    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 );
    487444        /**
    488445         * The WP_List_Table class does not handle pagination for us, so we need
     
    491448         */
    492449        //$data = array_slice($data,(($current_page-1)*$per_page),$per_page);
    493        
    494        
    495        
    496450        /**
    497451         * REQUIRED. Now we can add our *sorted* data to the items property, where
     
    499453         */
    500454        $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 );
    512462        /**
    513463         * REQUIRED. We also have to register our pagination options & calculations.
    514464         */
    515465        $this->set_pagination_args( array(
    516             'total_items' => $total_items,                  //WE have to calculate the total number of items
    517             'per_page'    => $per_page,                     //WE have to determine how many items to show on a page
    518             'total_pages' => ceil( $total_items / $per_page )   //WE have to calculate the total number of pages
     466            'total_items' => $total_items,
     467            'per_page'    => $per_page,
     468            'total_pages' => ceil( $total_items / $per_page ),
    519469        ) );
    520470    }
     471
    521472}
  • email-tracker/trunk/src/class-util.php

    r3340406 r3416646  
    115115
    116116        // Delete from email table
     117        // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    117118        $wpdb->query(
    118119            $wpdb->prepare(
     120                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared
    119121                "DELETE FROM " . self::emtr_get_table_name( 'email' ) . " WHERE email_id IN ($placeholders)",
    120122                $email_ids
     
    123125
    124126        // Delete from track_email_open_log table
     127        // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    125128        $wpdb->query(
    126129            $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)",
    128132                $email_ids
    129133            )
     
    131135
    132136        // Delete from track_email_link_click_log table
     137        // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    133138        $wpdb->query(
    134139            $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
    138143                $email_ids
    139144            )
     
    141146
    142147        // Delete from track_email_link_master table
     148        // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    143149        $wpdb->query(
    144150            $wpdb->prepare(
     151                // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
    145152                "DELETE FROM " . self::emtr_get_table_name( 'track_email_link_master' ) . " WHERE trklink_email_id IN ($placeholders)",
    146153                $email_ids
  • email-tracker/trunk/src/core/class-chunk-processor.php

    r3344738 r3416646  
    159159       
    160160        $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" ) );
    162162       
    163163        $table_name = $wpdb->prefix . 'emtr_email_logs';
    164164       
    165165        // Get emails to delete
     166        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    166167        $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
    171170                $date_threshold,
    172171                $chunk_size,
     
    183182       
    184183        // Delete related data
     184        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    185185        $wpdb->query(
    186186            $wpdb->prepare(
     187                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
    187188                "DELETE FROM {$wpdb->prefix}emtr_email_open_logs WHERE email_id IN ($placeholders)",
    188189                $email_ids
    189190            )
    190191        );
    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 ) );
    198194       
    199195        // 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 ) );
    206198       
    207199        return count( $emails );
     
    227219       
    228220        // Get emails to export
     221        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    229222        $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",
    234225                $chunk_size,
    235226                $offset
     
    243234       
    244235        // Append to CSV file
     236        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
    245237        $handle = fopen( $export_file, 'a' );
    246238       
     
    253245            fputcsv( $handle, $email );
    254246        }
    255        
     247        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
    256248        fclose( $handle );
    257249       
     
    275267            return 0;
    276268        }
    277        
     269        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
    278270        $handle = fopen( $import_file, 'r' );
    279271       
     
    298290           
    299291            // Insert email
     292            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
    300293            $wpdb->insert( $table_name, $data );
    301294            $processed++;
    302295        }
    303        
     296        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
    304297        fclose( $handle );
    305298       
  • email-tracker/trunk/src/core/class-name-space-auto-loader.php

    r2670982 r3416646  
    103103
    104104
    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 ) );
    106106    }
    107107
  • email-tracker/trunk/src/integrations/emtr.php

    r3344738 r3416646  
    55    if ( !isset( $emtr ) ) {
    66        // 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';
    88        $emtr = fs_dynamic_init( array(
    99            'id'             => '1811',
     
    1111            'type'           => 'plugin',
    1212            'public_key'     => 'pk_1ed59e732da6955b547b2f0daa319',
    13             'is_premium'     => true,
     13            'is_premium'     => false,
    1414            'premium_suffix' => 'Pro',
    1515            'has_addons'     => false,
  • email-tracker/trunk/src/model/class-trackemail.php

    r3344738 r3416646  
    11<?php
     2
    23namespace PrashantWP\Email_Tracker\Model;
    34
     
    89 * @subpackage model
    910 */
    10 
    11 if ( ! defined( 'ABSPATH' ) ) {
    12     exit; // Exit if accessed directly
     11if ( !defined( 'ABSPATH' ) ) {
     12    exit;
     13    // Exit if accessed directly
    1314}
    14 
    1515use PrashantWP\Email_Tracker\Util;
    16 
    1716class 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.*,
    310237                (
    311238                    SELECT COUNT(*) FROM  ' . Util::emtr_get_table_name( 'track_email_link_click_log' ) . ' TEC
     
    316243                    WHERE TEC.trklinkclick_trklink_id = TEM.trklink_id
    317244                ) 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.*,
    332253                            (SELECT count(*) FROM ' . Util::emtr_get_table_name( 'track_email_open_log' ) . ' EOC WHERE EOC.trkemail_email_id = E.email_id) AS view_count,
    333254                            (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        }
    368283        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 ) {
    373287            //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 ) ) {
    382295            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    }
    390303
    391304}
  • email-tracker/trunk/track-email.php

    r3344738 r3416646  
    11<?php
     2
    23/**
    34 * To track email when email will be read
     
    67 * @subpackage track-email
    78 */
    8 
    99/*
    1010 * To access EMTR_Model function to call model object
    1111 */
    12 if ( ! defined( 'ABSPATH' ) ) {
    13     exit; // Exit if accessed directly
     12if ( !defined( 'ABSPATH' ) ) {
     13    exit;
     14    // Exit if accessed directly
    1415}
    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', '' ) );
     18if ( $emtr_pk == 0 ) {
     19    die;
     20}
    2321/*
    2422 * Display email track image
    2523 */
    2624// 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     }
     25if ( $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    }
    6153}
    62 
  • email-tracker/trunk/vendor/autoload.php

    r2728263 r3416646  
    33// autoload.php @generated by Composer
    44
     5if (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
    520require_once __DIR__ . '/composer/autoload_real.php';
    621
  • email-tracker/trunk/vendor/composer/ClassLoader.php

    r2671016 r3416646  
    4343class ClassLoader
    4444{
     45    /** @var \Closure(string):void */
     46    private static $includeFile;
     47
     48    /** @var string|null */
     49    private $vendorDir;
     50
    4551    // PSR-4
     52    /**
     53     * @var array<string, array<string, int>>
     54     */
    4655    private $prefixLengthsPsr4 = array();
     56    /**
     57     * @var array<string, list<string>>
     58     */
    4759    private $prefixDirsPsr4 = array();
     60    /**
     61     * @var list<string>
     62     */
    4863    private $fallbackDirsPsr4 = array();
    4964
    5065    // 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     */
    5173    private $prefixesPsr0 = array();
     74    /**
     75     * @var list<string>
     76     */
    5277    private $fallbackDirsPsr0 = array();
    5378
     79    /** @var bool */
    5480    private $useIncludePath = false;
     81
     82    /**
     83     * @var array<string, string>
     84     */
    5585    private $classMap = array();
     86
     87    /** @var bool */
    5688    private $classMapAuthoritative = false;
     89
     90    /**
     91     * @var array<string, bool>
     92     */
    5793    private $missingClasses = array();
     94
     95    /** @var string|null */
    5896    private $apcuPrefix;
    5997
     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     */
    60115    public function getPrefixes()
    61116    {
     
    67122    }
    68123
     124    /**
     125     * @return array<string, list<string>>
     126     */
    69127    public function getPrefixesPsr4()
    70128    {
     
    72130    }
    73131
     132    /**
     133     * @return list<string>
     134     */
    74135    public function getFallbackDirs()
    75136    {
     
    77138    }
    78139
     140    /**
     141     * @return list<string>
     142     */
    79143    public function getFallbackDirsPsr4()
    80144    {
     
    82146    }
    83147
     148    /**
     149     * @return array<string, string> Array of classname => path
     150     */
    84151    public function getClassMap()
    85152    {
     
    88155
    89156    /**
    90      * @param array $classMap Class to filename map
     157     * @param array<string, string> $classMap Class to filename map
     158     *
     159     * @return void
    91160     */
    92161    public function addClassMap(array $classMap)
     
    103172     * appending or prepending to the ones previously set for this prefix.
    104173     *
    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
    108179     */
    109180    public function add($prefix, $paths, $prepend = false)
    110181    {
     182        $paths = (array) $paths;
    111183        if (!$prefix) {
    112184            if ($prepend) {
    113185                $this->fallbackDirsPsr0 = array_merge(
    114                     (array) $paths,
     186                    $paths,
    115187                    $this->fallbackDirsPsr0
    116188                );
     
    118190                $this->fallbackDirsPsr0 = array_merge(
    119191                    $this->fallbackDirsPsr0,
    120                     (array) $paths
     192                    $paths
    121193                );
    122194            }
     
    127199        $first = $prefix[0];
    128200        if (!isset($this->prefixesPsr0[$first][$prefix])) {
    129             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
     201            $this->prefixesPsr0[$first][$prefix] = $paths;
    130202
    131203            return;
     
    133205        if ($prepend) {
    134206            $this->prefixesPsr0[$first][$prefix] = array_merge(
    135                 (array) $paths,
     207                $paths,
    136208                $this->prefixesPsr0[$first][$prefix]
    137209            );
     
    139211            $this->prefixesPsr0[$first][$prefix] = array_merge(
    140212                $this->prefixesPsr0[$first][$prefix],
    141                 (array) $paths
     213                $paths
    142214            );
    143215        }
     
    148220     * appending or prepending to the ones previously set for this namespace.
    149221     *
    150      * @param string       $prefix  The prefix/namespace, with trailing '\\'
    151      * @param array|string $paths   The PSR-4 base directories
    152      * @param bool         $prepend Whether to prepend the directories
     222     * @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
    153225     *
    154226     * @throws \InvalidArgumentException
     227     *
     228     * @return void
    155229     */
    156230    public function addPsr4($prefix, $paths, $prepend = false)
    157231    {
     232        $paths = (array) $paths;
    158233        if (!$prefix) {
    159234            // Register directories for the root namespace.
    160235            if ($prepend) {
    161236                $this->fallbackDirsPsr4 = array_merge(
    162                     (array) $paths,
     237                    $paths,
    163238                    $this->fallbackDirsPsr4
    164239                );
     
    166241                $this->fallbackDirsPsr4 = array_merge(
    167242                    $this->fallbackDirsPsr4,
    168                     (array) $paths
     243                    $paths
    169244                );
    170245            }
     
    176251            }
    177252            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
    178             $this->prefixDirsPsr4[$prefix] = (array) $paths;
     253            $this->prefixDirsPsr4[$prefix] = $paths;
    179254        } elseif ($prepend) {
    180255            // Prepend directories for an already registered namespace.
    181256            $this->prefixDirsPsr4[$prefix] = array_merge(
    182                 (array) $paths,
     257                $paths,
    183258                $this->prefixDirsPsr4[$prefix]
    184259            );
     
    187262            $this->prefixDirsPsr4[$prefix] = array_merge(
    188263                $this->prefixDirsPsr4[$prefix],
    189                 (array) $paths
     264                $paths
    190265            );
    191266        }
     
    196271     * replacing any others previously set for this prefix.
    197272     *
    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
    200277     */
    201278    public function set($prefix, $paths)
     
    212289     * replacing any others previously set for this namespace.
    213290     *
    214      * @param string       $prefix The prefix/namespace, with trailing '\\'
    215      * @param array|string $paths  The PSR-4 base directories
     291     * @param string              $prefix The prefix/namespace, with trailing '\\'
     292     * @param list<string>|string $paths  The PSR-4 base directories
    216293     *
    217294     * @throws \InvalidArgumentException
     295     *
     296     * @return void
    218297     */
    219298    public function setPsr4($prefix, $paths)
     
    235314     *
    236315     * @param bool $useIncludePath
     316     *
     317     * @return void
    237318     */
    238319    public function setUseIncludePath($useIncludePath)
     
    257338     *
    258339     * @param bool $classMapAuthoritative
     340     *
     341     * @return void
    259342     */
    260343    public function setClassMapAuthoritative($classMapAuthoritative)
     
    277360     *
    278361     * @param string|null $apcuPrefix
     362     *
     363     * @return void
    279364     */
    280365    public function setApcuPrefix($apcuPrefix)
     
    297382     *
    298383     * @param bool $prepend Whether to prepend the autoloader or not
     384     *
     385     * @return void
    299386     */
    300387    public function register($prepend = false)
    301388    {
    302389        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        }
    303401    }
    304402
    305403    /**
    306404     * Unregisters this instance as an autoloader.
     405     *
     406     * @return void
    307407     */
    308408    public function unregister()
    309409    {
    310410        spl_autoload_unregister(array($this, 'loadClass'));
     411
     412        if (null !== $this->vendorDir) {
     413            unset(self::$registeredLoaders[$this->vendorDir]);
     414        }
    311415    }
    312416
     
    315419     *
    316420     * @param  string    $class The name of the class
    317      * @return bool|null True if loaded, null otherwise
     421     * @return true|null True if loaded, null otherwise
    318422     */
    319423    public function loadClass($class)
    320424    {
    321425        if ($file = $this->findFile($class)) {
    322             includeFile($file);
     426            $includeFile = self::$includeFile;
     427            $includeFile($file);
    323428
    324429            return true;
    325430        }
     431
     432        return null;
    326433    }
    327434
     
    368475    }
    369476
     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     */
    370492    private function findFileWithExtension($class, $ext)
    371493    {
     
    433555        return false;
    434556    }
     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    }
    435579}
    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  
    11<?php
    22
    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 */
    1212
    1313namespace Composer;
    1414
     15use Composer\Autoload\ClassLoader;
    1516use Composer\Semver\VersionParser;
    1617
    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 */
    2227class InstalledVersions
    2328{
    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    }
    67396}
    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  
    33// autoload_classmap.php @generated by Composer
    44
    5 $vendorDir = dirname(dirname(__FILE__));
     5$vendorDir = dirname(__DIR__);
    66$baseDir = dirname($vendorDir);
    77
  • email-tracker/trunk/vendor/composer/autoload_namespaces.php

    r2653395 r3416646  
    33// autoload_namespaces.php @generated by Composer
    44
    5 $vendorDir = dirname(dirname(__FILE__));
     5$vendorDir = dirname(__DIR__);
    66$baseDir = dirname($vendorDir);
    77
  • email-tracker/trunk/vendor/composer/autoload_psr4.php

    r2653395 r3416646  
    33// autoload_psr4.php @generated by Composer
    44
    5 $vendorDir = dirname(dirname(__FILE__));
     5$vendorDir = dirname(__DIR__);
    66$baseDir = dirname($vendorDir);
    77
  • email-tracker/trunk/vendor/composer/autoload_real.php

    r2728263 r3416646  
    2626
    2727        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__));
    2929        spl_autoload_unregister(array('ComposerAutoloaderInited4140dc717c0cb32f19cd1b5ae4af0a', 'loadClassLoader'));
    3030
    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));
    5233
    5334        $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        }
    5447
    5548        return $loader;
  • email-tracker/trunk/vendor/composer/autoload_static.php

    r2728263 r3416646  
    77class ComposerStaticInited4140dc717c0cb32f19cd1b5ae4af0a
    88{
     9    public static $files = array (
     10        '8d50dc88e56bace65e1e72f6017983ed' => __DIR__ . '/..' . '/freemius/wordpress-sdk/start.php',
     11    );
     12
    913    public static $prefixLengthsPsr4 = array (
    1014        'S' =>
  • email-tracker/trunk/vendor/composer/installed.json

    r2653395 r3416646  
    22    "packages": [
    33        {
     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        {
    460            "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",
    763            "source": {
    864                "type": "git",
    965                "url": "https://github.com/soundasleep/html2text.git",
    10                 "reference": "3243a7107878a61685d2eccf99918d6479e039fc"
     66                "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3"
    1167            },
    1268            "dist": {
    1369                "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",
    1672                "shasum": ""
    1773            },
     
    1975                "ext-dom": "*",
    2076                "ext-libxml": "*",
    21                 "php": ">=7.0"
     77                "php": "^7.3|^8.0"
    2278            },
    2379            "require-dev": {
    24                 "phpunit/phpunit": "~7.0",
    25                 "soundasleep/component-tests": "~0.2"
     80                "phpstan/phpstan": "^1.9",
     81                "phpunit/phpunit": "^7.0|^8.0|^9.0"
    2682            },
    27             "time": "2019-02-15T01:44:54+00:00",
     83            "time": "2023-01-06T09:28:15+00:00",
    2884            "type": "library",
    2985            "installation-source": "dist",
     
    55111                "email": "support@jevon.org",
    56112                "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"
    58114            },
    59115            "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,
    811    ),
    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        ),
    2240    ),
    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   ),
    3341);
  • email-tracker/trunk/vendor/composer/platform_check.php

    r2653395 r3416646  
    55$issues = array();
    66
    7 if (!(PHP_VERSION_ID >= 70000)) {
    8     $issues[] = 'Your Composer dependencies require a PHP version ">= 7.0.0". You are running ' . PHP_VERSION . '.';
     7if (!(PHP_VERSION_ID >= 70300)) {
     8    $issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.';
    99}
    1010
  • email-tracker/trunk/vendor/soundasleep/html2text/.gitignore

    r2653395 r3416646  
    44vendor/
    55**/*.DS_Store
     6.phpunit.result.cache
     7composer.lock
  • email-tracker/trunk/vendor/soundasleep/html2text/README.md

    r2653395 r3416646  
    1 html2text [![Build Status](https://travis-ci.org/soundasleep/html2text.svg?branch=master)](https://travis-ci.org/soundasleep/html2text) [![Total Downloads](https://poser.pugx.org/soundasleep/html2text/downloads.png)](https://packagist.org/packages/soundasleep/html2text)
     1![example workflow](https://github.com/soundasleep/html2text/actions/workflows/test.yml/badge.svg) [![Total Downloads](https://poser.pugx.org/soundasleep/html2text/downloads.png)](https://packagist.org/packages/soundasleep/html2text)
    22=========
    33
     
    7272| **ignore_errors** | `false` | Set to `true` to ignore any XML parsing errors. |
    7373| **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 |
    7475
    7576Pass along options as a second argument to `convert`, for example:
     
    9192### Class 'DOMDocument' not found
    9293
    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`
     94You 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`
    9495
    9596## License
  • email-tracker/trunk/vendor/soundasleep/html2text/composer.json

    r2653395 r3416646  
    2222  },
    2323  "require": {
    24     "php": ">=7.0",
     24    "php": "^7.3|^8.0",
    2525    "ext-dom": "*",
    2626    "ext-libxml": "*"
    2727  },
    2828  "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"
    3131  }
    3232}
  • email-tracker/trunk/vendor/soundasleep/html2text/src/Html2Text.php

    r2653395 r3416646  
    55class Html2Text {
    66
    7     public static function defaultOptions() {
    8         return array(
     7    /** @return array<string, bool | string> */
     8    public static function defaultOptions(): array {
     9        return [
    910            'ignore_errors' => false,
    1011            'drop_links'    => false,
    11         );
     12            'char_set'      => 'auto'
     13        ];
    1214    }
    1315
     
    2325     *
    2426     * @param string $html the input HTML
    25      * @param boolean $ignore_error Ignore xml parsing errors
     27     * @param boolean|array<string, bool | string> $options if boolean, Ignore xml parsing errors, else ['ignore_errors' => false, 'drop_links' => false, 'char_set' => 'auto']
    2628     * @return string the HTML converted, as best as possible, to text
    2729     * @throws Html2TextException if the HTML could not be loaded as a {@link \DOMDocument}
    2830     */
    29     public static function convert($html, $options = array()) {
     31    public static function convert(string $html, $options = []): string {
    3032
    3133        if ($options === false || $options === true) {
    3234            // Using old style (< 1.0) of passing in options
    33             $options = array('ignore_errors' => $options);
     35            $options = ['ignore_errors' => $options];
    3436        }
    3537
     
    3941        foreach ($options as $key => $value) {
    4042            if (!in_array($key, array_keys(static::defaultOptions()))) {
    41                 throw new \InvalidArgumentException("Unknown html2text option '$key'");
    42             }
    43         }
    44 
    45         $is_office_document = static::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);
    4648
    4749        if ($is_office_document) {
    4850            // 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)) {
    5458            $html = mb_convert_encoding($html, "HTML-ENTITIES", "UTF-8");
    5559        }
    5660
    57         $doc = static::getDocument($html, $options['ignore_errors']);
    58 
    59         $output = static::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);
    6064
    6165        // process output for whitespace/newlines
    62         $output = static::processWhitespaceNewlines($output);
     66        $output = self::processWhitespaceNewlines($output);
    6367
    6468        return $output;
     
    7377     * @return string the fixed text
    7478     */
    75     static function fixNewlines($text) {
     79    public static function fixNewlines(string $text): string {
    7680        // replace \r\n to \n
    7781        $text = str_replace("\r\n", "\n", $text);
     
    8286    }
    8387
    84     static function nbspCodes() {
    85         return array(
     88    /** @return array<string> */
     89    public static function nbspCodes(): array {
     90        return [
    8691            "\xc2\xa0",
    8792            "\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 [
    9399            "\xe2\x80\x8c",
    94100            "\u200c",
    95         );
     101        ];
    96102    }
    97103
     
    102108     * @return string the fixed text
    103109     */
    104     static function processWhitespaceNewlines($text) {
     110    public static function processWhitespaceNewlines(string $text): string {
    105111
    106112        // remove excess spaces around tabs
     
    116122        // do it here so they do NOT get removed with other leading spaces, as they
    117123        // are sometimes used for indentation
    118         $text = static::renderText($text);
     124        $text = self::renderText($text);
    119125
    120126        // remove trailing whitespace
     
    125131
    126132        // unarmor pre blocks
    127         $text = static::fixNewLines($text);
     133        $text = self::fixNewLines($text);
    128134
    129135        // remove unnecessary empty lines
     
    131137
    132138        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;
    133150    }
    134151
     
    137154     *
    138155     * @param string $html the input HTML
    139      * @param boolean $ignore_error Ignore xml parsing errors
     156     * @param array<string, bool | string> $options
    140157     * @return \DOMDocument the parsed document tree
    141158     */
    142     static function getDocument($html, $ignore_error = false) {
     159    private static function getDocument(string $html, array $options): \DOMDocument {
    143160
    144161        $doc = new \DOMDocument();
     
    160177        }
    161178
    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'])) {
    163198            $doc->strictErrorChecking = false;
    164199            $doc->recover = true;
    165200            $doc->xmlStandalone = true;
    166201            $old_internal_errors = libxml_use_internal_errors(true);
    167             $load_result = $doc->loadHTML($html, LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NONET | LIBXML_PARSEHUGE);
     202            $load_result = $doc->loadHTML($header . $html, LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NONET | LIBXML_PARSEHUGE);
    168203            libxml_use_internal_errors($old_internal_errors);
    169204        }
    170205        else {
    171             $load_result = $doc->loadHTML($html);
     206            $load_result = $doc->loadHTML($header . $html);
    172207        }
    173208
     
    177212
    178213        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;
    186214    }
    187215
     
    194222     * by a browser.
    195223     */
    196     static function renderText($text) {
    197         $text = str_replace(static::nbspCodes(), " ", $text);
    198         $text = str_replace(static::zwnjCodes(), "", $text);
     224    private static function renderText(string $text): string {
     225        $text = str_replace(self::nbspCodes(), " ", $text);
     226        $text = str_replace(self::zwnjCodes(), "", $text);
    199227        return $text;
    200228    }
    201229
    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 {
    207231        // get the next child
    208232        $nextNode = $node->nextSibling;
    209233        while ($nextNode != null) {
    210234            if ($nextNode instanceof \DOMText) {
    211                 if (!static::isWhitespace($nextNode->wholeText)) {
     235                if (!self::isWhitespace($nextNode->wholeText)) {
    212236                    break;
    213237                }
     
    229253    }
    230254
    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 {
    232257        if ($node instanceof \DOMText) {
    233258          // Replace whitespace characters with a space (equivilant to \s)
    234259            if ($in_pre) {
    235                 $text = "\n" . trim(static::renderText($node->wholeText), "\n\r\t ") . "\n";
     260                $text = "\n" . trim(self::renderText($node->wholeText), "\n\r\t ") . "\n";
    236261
    237262                // Remove trailing whitespace only
     
    241266                return str_replace("\n", "\r", $text);
    242267
    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;
    252276        }
    253277
     
    258282
    259283        $name = strtolower($node->nodeName);
    260         $nextName = static::nextChildName($node);
     284        $nextName = self::nextChildName($node);
    261285
    262286        // start whitespace
     
    303327                // classname in any Microsoft export or outlook for a paragraph that behaves
    304328                // like a line return) we skip the first line returns and set the name to br.
     329                // @phpstan-ignore-next-line
    305330                if ($is_office_document && $node->getAttribute('class') == 'MsoNormal') {
    306331                    $output = "";
     
    342367
    343368            $n = $node->childNodes->item(0);
    344             $previousSiblingNames = array();
     369            $previousSiblingNames = [];
    345370            $previousSiblingName = null;
    346371
    347             $parts = array();
     372            $parts = [];
    348373            $trailing_whitespace = 0;
    349374
    350375            while ($n != null) {
    351376
    352                 $text = static::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);
    353378
    354379                // Pass current node name to next child, as previousSibling does not appear to get populated
    355380                if ($n instanceof \DOMDocumentType
    356381                    || $n instanceof \DOMProcessingInstruction
    357                     || ($n instanceof \DOMText && static::isWhitespace($text))) {
     382                    || ($n instanceof \DOMText && self::isWhitespace($text))) {
    358383                    // Keep current previousSiblingName, these are invisible
    359384                    $trailing_whitespace++;
     
    412437            case "a":
    413438                // links are returned in [text](link) format
     439                // @phpstan-ignore-next-line
    414440                $href = $node->getAttribute("href");
    415441
     
    421447
    422448                    // for linking images, the title of the <a> overrides the title of the <img>
     449                    // @phpstan-ignore-next-line
    423450                    if ($node->getAttribute("title")) {
     451                        // @phpstan-ignore-next-line
    424452                        $output = $node->getAttribute("title");
    425453                    }
     
    427455
    428456                // if there is no link text, but a title attr
     457                // @phpstan-ignore-next-line
    429458                if (!$output && $node->getAttribute("title")) {
     459                    // @phpstan-ignore-next-line
    430460                    $output = $node->getAttribute("title");
    431461                }
     
    433463                if ($href == null) {
    434464                    // it doesn't link anywhere
     465                    // @phpstan-ignore-next-line
    435466                    if ($node->getAttribute("name") != null) {
    436467                        if ($options['drop_links']) {
     
    468499
    469500            case "img":
     501                // @phpstan-ignore-next-line
    470502                if ($node->getAttribute("title")) {
     503                    // @phpstan-ignore-next-line
    471504                    $output = "[" . $node->getAttribute("title") . "]";
     505                // @phpstan-ignore-next-line
    472506                } elseif ($node->getAttribute("alt")) {
     507                    // @phpstan-ignore-next-line
    473508                    $output = "[" . $node->getAttribute("alt") . "]";
    474509                } else {
     
    483518            case "blockquote":
    484519                // process quoted text for whitespace/newlines
    485                 $output = static::processWhitespaceNewlines($output);
     520                $output = self::processWhitespaceNewlines($output);
    486521
    487522                // add leading newline
  • email-tracker/trunk/vendor/soundasleep/html2text/src/Html2TextException.php

    r2653395 r3416646  
    55class Html2TextException extends \Exception {
    66
    7     var $more_info;
     7    /** @var string $more_info */
     8    public $more_info;
    89
    9     public function __construct($message = "", $more_info = "") {
     10    public function __construct(string $message = "", string $more_info = "") {
    1011        parent::__construct($message);
    1112        $this->more_info = $more_info;
Note: See TracChangeset for help on using the changeset viewer.