├── tests ├── _output │ └── .gitignore ├── _data │ └── dump.sql ├── unit │ └── _bootstrap.php ├── functional │ ├── _bootstrap.php │ └── LogPageTestCept.php ├── integration │ └── _bootstrap.php ├── _bootstrap.php ├── acceptance │ └── _bootstrap.php ├── unit.suite.yml ├── _support │ ├── Helper │ │ ├── Unit.php │ │ ├── Acceptance.php │ │ ├── Functional.php │ │ └── Integration.php │ ├── UnitTester.php │ ├── AcceptanceTester.php │ ├── FunctionalTester.php │ ├── IntegrationTester.php │ └── _generated │ │ └── IntegrationTesterActions.php ├── integration.suite.yml ├── functional.suite.yml ├── acceptance.suite.yml └── wp-tests │ ├── Core │ ├── DB │ │ └── TableManagerTest.php │ ├── EmailLoggerTest.php │ ├── UI │ │ ├── ListTable │ │ │ └── LogListTableTest.php │ │ └── Component │ │ │ └── AdminUIEnhancerTest.php │ └── EmailLogTest.php │ ├── Util │ ├── CheckedArrayTest.php │ ├── SanitizeEmailTest.php │ └── EmailHeaderParserTest.php │ ├── bootstrap.php │ ├── uninstall │ ├── UninstallWithoutDeleteTest.php │ └── UninstallWithDeleteTest.php │ └── EmailLogAutoloaderTest.php ├── .scrutinizer.yml ├── .gitignore ├── languages ├── email-log-de_DE.mo ├── email-log-lt_LT.mo ├── email-log-nl_NL.mo ├── email-log-de_DE.po ├── email-log-lt_LT.po └── email-log-nl_NL.po ├── assets-wp-repo ├── icon-128x128.png ├── icon-256x256.png ├── screenshot-1.png ├── screenshot-2.png ├── screenshot-3.png ├── screenshot-4.png ├── screenshot-5.png ├── banner-1544x500.png ├── banner-772x250.png ├── banner-772x250-rtl.png └── banner-1544x500-rtl.png ├── AUTHORS.md ├── bin ├── phpcs.sh └── install-wp-tests.sh ├── include ├── Core │ ├── UI │ │ ├── Setting │ │ │ ├── SettingField.php │ │ │ ├── SettingSection.php │ │ │ └── Setting.php │ │ ├── Component │ │ │ ├── DashboardWidget.php │ │ │ ├── AdminUIEnhancer.php │ │ │ └── EmailLogSystemInfo.php │ │ ├── Page │ │ │ ├── AddonListPage.php │ │ │ ├── SystemInfoPage.php │ │ │ ├── SettingsPage.php │ │ │ ├── BasePage.php │ │ │ └── LogListPage.php │ │ └── UILoader.php │ ├── Loadie.php │ ├── AdminCapabilityGiver.php │ ├── Request │ │ ├── OverridePluginAPI.php │ │ ├── NonceChecker.php │ │ └── LogListAction.php │ ├── EmailLog.php │ └── EmailLogger.php ├── compatibility │ ├── EmailLog.php │ └── wpmandrill.php ├── Addon │ ├── License │ │ ├── AddonLicense.php │ │ ├── BundleLicense.php │ │ └── BaseLicense.php │ ├── addon-helper.php │ ├── EmailLogAddon.php │ ├── AddonUpdater.php │ ├── DependencyEnforcer.php │ ├── API │ │ ├── EDDUpdater.php │ │ └── EDDAPI.php │ ├── Upseller.php │ └── AddonList.php ├── Util │ └── EmailHeaderParser.php └── EmailLogAutoloader.php ├── phpdoc.dist.xml ├── .editorconfig ├── assets ├── js │ └── admin │ │ ├── addon-list.js │ │ └── view-logs.js └── css │ └── admin │ ├── view-logs.css │ └── addon-list.css ├── phpunit.xml.dist ├── composer.json ├── package.json ├── phpcs.xml ├── codeception.yml ├── uninstall.php ├── .styleci.yml ├── Gruntfile.js ├── email-log.php ├── .travis.yml ├── load-email-log.php └── README.md /tests/_output/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /tests/_data/dump.sql: -------------------------------------------------------------------------------- 1 | /* Replace this file with actual dump of your database */ -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | tools: 2 | external_code_coverage: 3 | timeout: 600 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | 3 | dist/ 4 | code-coverage/ 5 | node_modules/ 6 | vendor/ 7 | 8 | tests/_output/* 9 | -------------------------------------------------------------------------------- /tests/unit/_bootstrap.php: -------------------------------------------------------------------------------- 1 | wantTo('Ensure the log page is displayed'); 4 | 5 | $I->loginAsAdmin(); 6 | 7 | $I->amOnPluginsPage(); 8 | 9 | $I->seePluginActivated('email-log'); 10 | -------------------------------------------------------------------------------- /tests/_support/Helper/Unit.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Bulk Delete 4 | 5 | docs/codex 6 | 7 | 8 | docs/codex 9 | 10 | 11 | . 12 | include/libraries/* 13 | test/* 14 | dist/* 15 | node_modules/* 16 | vendor/* 17 | docs/* 18 | 19 | 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | # WordPress Coding Standards 5 | # https://make.wordpress.org/core/handbook/coding-standards/ 6 | 7 | root = true 8 | 9 | [*] 10 | charset = utf-8 11 | end_of_line = lf 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | indent_style = tab 15 | 16 | [{.jshintrc, *.json, *.yml}] 17 | indent_style = space 18 | indent_size = 2 19 | 20 | [{*.txt,wp-config-sample.php}] 21 | end_of_line = crlf 22 | -------------------------------------------------------------------------------- /include/Core/Loadie.php: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | ./tests/wp-tests/ 12 | 13 | 14 | 15 | 16 | 17 | uninstall 18 | uninstall-delete 19 | 20 | 21 | 22 | 23 | 24 | include 25 | email-log.php 26 | uninstall.php 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /include/Addon/License/AddonLicense.php: -------------------------------------------------------------------------------- 1 | license_data ) ) { 19 | return parent::get_license_key(); 20 | } 21 | 22 | return $this->license_data->license_key; 23 | } 24 | 25 | /** 26 | * Option name in which individual license data is stored. 27 | * This method should be called only after setting the add-on name. 28 | * 29 | * @return string Option name. 30 | */ 31 | protected function get_option_name() { 32 | return 'el_license_' . md5( $this->get_addon_name() ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /assets/css/admin/view-logs.css: -------------------------------------------------------------------------------- 1 | #search_id-search-date-input { 2 | float: left; 3 | height: 28px; 4 | margin: 0 4px 0 0; 5 | } 6 | 7 | #tabs { 8 | margin-top: 10px; 9 | } 10 | 11 | .tabs-text-pre { 12 | height: 100%; 13 | width: 100%; 14 | } 15 | 16 | #tabs-preview, 17 | #tabs-text { 18 | height: 335px; 19 | overflow: auto; 20 | } 21 | 22 | #thickbox-footer-close { 23 | margin-top: 10px; 24 | } 25 | 26 | #thickbox-footer-close:hover { 27 | background: #eee; 28 | color: #666; 29 | } 30 | 31 | #TB_ajaxContent { 32 | padding-bottom: 10px !important; /* Override the default Thickbox css values. */ 33 | } 34 | 35 | #el-pro-msg { 36 | display: inline-block; 37 | margin: 7px 0; 38 | } 39 | 40 | .column-result .dashicons { 41 | font-size: xx-large; 42 | } 43 | 44 | .column-result .dashicons-yes-alt { 45 | color: #00C853; 46 | } 47 | 48 | .column-result .dashicons-dismiss { 49 | color: #E53935; 50 | } 51 | -------------------------------------------------------------------------------- /tests/wp-tests/Core/DB/TableManagerTest.php: -------------------------------------------------------------------------------- 1 | table_manager = new TableManager; 11 | } 12 | 13 | public function test_get_log_table_name() { 14 | global $wpdb; 15 | 16 | $expected = $wpdb->prefix . 'email_log'; 17 | $actual = $this->table_manager->get_log_table_name(); 18 | 19 | $this->assertEquals( $expected, $actual ); 20 | } 21 | 22 | public function test_on_delete_blog() { 23 | $tables = array( 24 | 'some-table-name', 25 | ); 26 | 27 | $table_name = $this->table_manager->get_log_table_name(); 28 | $expected = array_merge( $tables, array( $table_name ) ); 29 | 30 | $actual = $this->table_manager->delete_table_from_deleted_blog( $tables ); 31 | 32 | $this->assertEquals( $expected, $actual ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /include/Addon/addon-helper.php: -------------------------------------------------------------------------------- 1 | loader->add_namespace( 'EmailLog', $addon_dir . 'include' ); 25 | 26 | $addon_updater = null; 27 | 28 | if ( \EmailLog\Util\is_admin_non_ajax_request() ) { 29 | $addon_updater = new \EmailLog\Addon\AddonUpdater( $addon_file ); 30 | } 31 | 32 | $addon = new $addon_class( $addon_file, $addon_updater ); 33 | 34 | add_action( 'el_loaded', array( $addon, 'load' ) ); 35 | 36 | return $addon; 37 | } 38 | -------------------------------------------------------------------------------- /tests/wp-tests/Core/EmailLoggerTest.php: -------------------------------------------------------------------------------- 1 | getMockBuilder( '\\EmailLog\\Core\\DB\\TableManager' )->getMock(); 15 | $table_manager_stub->method( 'insert_log' ); 16 | 17 | $email_log->table_manager = $table_manager_stub; 18 | 19 | $this->logger = new EmailLogger(); 20 | } 21 | 22 | public function test_filter_doesnt_change_mailinfo() { 23 | $mail_info = array( 24 | 'attachments' => array(), 25 | 'to' => array( 'sudar@sudarmuthu.com' ), 26 | 'subject' => 'Email subject', 27 | 'headers' => array(), 28 | ); 29 | 30 | $actual = $this->logger->log_email( $mail_info ); 31 | 32 | $this->assertEquals( $mail_info, $actual ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sudar/email-log", 3 | "description": "Email Log WordPress plugin", 4 | "type": "wordpress-plugin", 5 | "license": "GPL-2.0-or-later", 6 | "authors": [ 7 | { 8 | "name": "Sudar Muthu", 9 | "homepage": "https://sudarmuthu.com" 10 | } 11 | ], 12 | "support": { 13 | "issues": "https://github.com/sudar/email-log/issues" 14 | }, 15 | "config": { 16 | "sort-packages": true 17 | }, 18 | "repositories": [ 19 | { 20 | "type": "vcs", 21 | "url": "https://github.com/sudar/wp-system-info" 22 | } 23 | ], 24 | "require": { 25 | "php": ">=5.6", 26 | "ext-json": "*", 27 | "collizo4sky/persist-admin-notices-dismissal": "^1.4", 28 | "sudar/wp-system-info": "dev-master" 29 | }, 30 | "require-dev": { 31 | "phpunit/phpunit": "^5.0", 32 | "codeception/codeception": "^2.2", 33 | "lucatume/wp-browser": "^1.14", 34 | "jdgrimes/wp-plugin-uninstall-tester": "~0.6", 35 | "squizlabs/php_codesniffer": "^3.0", 36 | "dealerdirect/phpcodesniffer-composer-installer": "^0.5", 37 | "phpcompatibility/php-compatibility": "^9.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/wp-tests/Util/CheckedArrayTest.php: -------------------------------------------------------------------------------- 1 | array( 'editor', 'author', 'subscriber' ), 21 | 'current' => 'editor' 22 | ), 23 | "checked='checked'" 24 | ), 25 | // Failure test case. 26 | array( 27 | array( 28 | 'values' => 'editor', 29 | 'current' => 'editor' 30 | ), 31 | '' 32 | ) 33 | ); 34 | } 35 | 36 | /** 37 | * Test $values is array. 38 | * 39 | * @dataProvider provider_to_test_checked_array 40 | */ 41 | function test_checked_array( $input, $expected ) { 42 | ob_start(); 43 | checked_array( $input['values'], $input['current'] ); 44 | $actual = ob_get_clean(); 45 | $this->assertSame( $expected, $actual ); 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /tests/wp-tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | file = str_replace( 'tests/wp-tests/Core/', '', __FILE__ ); 26 | $page = new MockLogListPage( $this->file ); 27 | $page->load(); 28 | $this->log_list_table = new LogListTable( $page ); 29 | } 30 | 31 | public function test_get_columns() { 32 | $actual = $this->log_list_table->get_columns(); 33 | 34 | $this->assertArrayHasKey( 'cb', $actual ); 35 | $this->assertArrayHasKey( 'sent_date', $actual ); 36 | $this->assertArrayHasKey( 'to_email', $actual ); 37 | $this->assertArrayHasKey( 'subject', $actual ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /include/compatibility/wpmandrill.php: -------------------------------------------------------------------------------- 1 | file = str_replace( 'tests/wp-tests/Core/', '', __FILE__ ); 14 | 15 | // Create a stub for EmailLogAutoloader class. 16 | $loader_stub = $this->getMockBuilder( '\\EmailLog\\EmailLogAutoloader' )->getMock(); 17 | 18 | // Create a stub for Table Manager class. 19 | $table_manager_stub = $this->getMockBuilder( '\\EmailLog\\Core\\DB\\TableManager' )->getMock(); 20 | $table_manager_stub->method( 'load' ); 21 | 22 | // Create a stub for Email Logger class. 23 | $email_logger_stub = $this->getMockBuilder( '\\EmailLog\\Core\\EmailLogger' )->getMock(); 24 | $email_logger_stub->method( 'load' ); 25 | 26 | $this->email_log = new EmailLog( $this->file, $loader_stub, $table_manager_stub ); 27 | } 28 | 29 | public function tearDown() { 30 | parent::tearDown(); 31 | } 32 | 33 | /** 34 | * Test translations_path. 35 | */ 36 | public function test_translations_path() { 37 | $this->email_log->load(); 38 | 39 | $expected = dirname( plugin_basename( $this->file ) ) . '/languages/'; 40 | $actual = $this->email_log->translations_path; 41 | 42 | $this->assertEquals( $expected, $actual ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /assets/css/admin/addon-list.css: -------------------------------------------------------------------------------- 1 | .el-addon-list { 2 | display: grid; 3 | grid-gap: 10px; 4 | grid-template-columns: repeat(auto-fit, 350px); 5 | } 6 | 7 | .el-addon { 8 | background: #FFF; 9 | border: 1px solid #ccc; 10 | box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); 11 | padding: 10px; 12 | } 13 | 14 | .el-addon-image, 15 | .individual-license .el-license { 16 | width: 330px; 17 | } 18 | 19 | .el-addon-list .disabled { 20 | cursor: not-allowed !important; 21 | } 22 | 23 | .bundle-license { 24 | margin-bottom: 3%; 25 | } 26 | 27 | .bundle-license .notice { 28 | padding-top: 10px; 29 | padding-bottom: 10px; 30 | } 31 | 32 | .bundle-license .el-license, .bundle-license .button { 33 | font-size: 1.7em; 34 | } 35 | 36 | .bundle-license .el-license, 37 | .bundle-license .button, 38 | .individual-license .el-license, 39 | .individual-license .button { 40 | line-height: 2; 41 | } 42 | 43 | .bundle-license .expires { 44 | margin-left: 5px; 45 | margin-top: 5px; 46 | } 47 | 48 | .individual-license { 49 | padding-top: 10px; 50 | } 51 | 52 | .individual-license .el-license { 53 | padding-left: 10px; 54 | } 55 | 56 | .individual-license .button { 57 | margin-top: 10px; 58 | } 59 | 60 | .el-expander { 61 | float: right; 62 | font-size: 40px; 63 | margin-top: -5px; 64 | margin-right: 10px; 65 | } 66 | 67 | @media screen and (max-width: 782px) { 68 | .bundle-license .el-license, .bundle-license .button { 69 | font-size: 0.8em; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/wp-tests/uninstall/UninstallWithoutDeleteTest.php: -------------------------------------------------------------------------------- 1 | plugin_file = 'email-log/email-log.php'; 25 | 26 | parent::setUp(); 27 | } 28 | 29 | /** 30 | * Test installation and uninstallation without deleting table. 31 | */ 32 | public function test_uninstall_without_deleting_table() { 33 | global $wpdb; 34 | 35 | /* 36 | * First test that the plugin installed itself properly. 37 | */ 38 | 39 | // Check that a database table was added. 40 | $this->assertTableExists( $wpdb->prefix . 'email_log' ); 41 | 42 | // Check that an option was added to the database. 43 | $this->assertEquals( '0.3', get_option( 'email-log-db' ) ); 44 | 45 | /* 46 | * Now, test that it uninstalls itself properly. 47 | * By default table should not be deleted. 48 | */ 49 | 50 | // You must call this to perform uninstallation. 51 | $this->uninstall(); 52 | 53 | // Check that the table was deleted. 54 | $this->assertTableExists( $wpdb->prefix . 'email_log' ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /include/Core/UI/Setting/SettingSection.php: -------------------------------------------------------------------------------- 1 | fields[] = $field; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /include/Addon/EmailLogAddon.php: -------------------------------------------------------------------------------- 1 | addon_file = $addon_file; 43 | $this->updater = $updater; 44 | 45 | $this->initialize(); 46 | } 47 | 48 | /** 49 | * Load the add-on and setup hooks. 50 | */ 51 | public function load() { 52 | if ( \EmailLog\Util\is_admin_non_ajax_request() ) { 53 | $email_log = email_log(); 54 | 55 | if ( ! $email_log->is_plugin_api_overridden() ) { 56 | $override_plugin_api = new \EmailLog\Core\Request\OverridePluginAPI(); 57 | $override_plugin_api->load(); 58 | 59 | $email_log->plugin_api_overridden(); 60 | } 61 | } 62 | 63 | if ( is_null( $this->updater ) ) { 64 | return; 65 | } 66 | 67 | $this->updater->set_addon_data( $this->addon_name, $this->addon_version, $this->addon_author ); 68 | $this->updater->load(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /include/Core/AdminCapabilityGiver.php: -------------------------------------------------------------------------------- 1 | roles ) ) { 34 | return $allcaps; 35 | } 36 | 37 | if ( array_key_exists( LogListPage::CAPABILITY, $allcaps ) ) { 38 | return $allcaps; 39 | } 40 | 41 | $allcaps[ LogListPage::CAPABILITY ] = true; 42 | 43 | return $allcaps; 44 | } 45 | 46 | /** 47 | * Add Manage Email Logs capability to administrator role. 48 | * This will be called on install. 49 | */ 50 | public function add_cap_to_admin() { 51 | $admin = get_role( 'administrator' ); 52 | 53 | if ( is_null( $admin ) ) { 54 | return; 55 | } 56 | 57 | $admin->add_cap( LogListPage::CAPABILITY ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /include/Addon/AddonUpdater.php: -------------------------------------------------------------------------------- 1 | addon_file = $addon_file; 27 | } 28 | 29 | /** 30 | * Set Add-on data. 31 | * 32 | * @param string $addon_name Add-on Name. 33 | * @param string $addon_version Add-on Version. 34 | * @param string $addon_author Add-on Author. 35 | */ 36 | public function set_addon_data( $addon_name, $addon_version, $addon_author ) { 37 | $this->addon_name = $addon_name; 38 | $this->addon_version = $addon_version; 39 | $this->addon_author = $addon_author; 40 | } 41 | 42 | /** 43 | * Set up hooks and load the license handler. 44 | * This method is called on `wp-loaded` hook. 45 | */ 46 | public function load() { 47 | add_action( 'admin_init', array( $this, 'setup_updater' ) ); 48 | } 49 | 50 | /** 51 | * Setup up Add-on auto-updater using EDD library. 52 | */ 53 | public function setup_updater() { 54 | $email_log = email_log(); 55 | $licenser = $email_log->get_licenser(); 56 | 57 | if ( is_null( $licenser ) ) { 58 | return; 59 | } 60 | 61 | $license_key = $licenser->get_addon_license_key( $this->addon_name ); 62 | 63 | $updater = new EDDUpdater( $email_log->get_store_url(), $this->addon_file, array( 64 | 'version' => $this->addon_version, 65 | 'license' => $license_key, 66 | 'item_name' => $this->addon_name, 67 | 'author' => $this->addon_author, 68 | ) 69 | ); 70 | 71 | $licenser->add_updater( $updater ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /include/Core/UI/Component/DashboardWidget.php: -------------------------------------------------------------------------------- 1 | table_manager->get_logs_count(); 40 | ?> 41 | 42 |

43 | : 44 |

45 | 46 | 55 | 56 | 61 | 62 | 2 | 3 | Email Log coding standard 4 | 5 | ./ 6 | 7 | 8 | docs/* 9 | dist/* 10 | code-coverage/* 11 | node_modules/* 12 | test/* 13 | tests/* 14 | vendor/* 15 | Gruntfile.js 16 | 17 | 18 | include/libraries/* 19 | 20 | 21 | assets/css/vendor/* 22 | assets/css/*.min.css 23 | 24 | assets/js/vendor/* 25 | assets/js/*.min.js 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /tests/wp-tests/Core/UI/Component/AdminUIEnhancerTest.php: -------------------------------------------------------------------------------- 1 | plugin_basename; 15 | } 16 | } 17 | 18 | /** 19 | * Test PluginList Enhancer. 20 | * 21 | * @since 2.0 22 | */ 23 | class AdminUIEnhancerTest extends \PHPUnit_Framework_TestCase { 24 | 25 | protected $file; 26 | protected $plugin_list_enhancer; 27 | 28 | public function setUp() { 29 | parent::setUp(); 30 | $this->file = str_replace( 'tests/wp-tests/Core/UI/', '', __FILE__ ); 31 | 32 | $this->plugin_list_enhancer = new MockAdminUIEnhancerClass( $this->file ); 33 | } 34 | 35 | public function test_plugin_basename() { 36 | $expected = plugin_basename( $this->file ); 37 | $actual = $this->plugin_list_enhancer->get_plugin_basename(); 38 | 39 | $this->assertEquals( $expected, $actual ); 40 | } 41 | 42 | public function test_row_meta_filter_not_changed_for_other_plugin() { 43 | $links = array(); 44 | $plugin = 'some-other-plugin'; 45 | 46 | $actual = $this->plugin_list_enhancer->insert_addon_store_link( $links, $plugin ); 47 | 48 | $this->assertcount( count( $links ), $actual ); 49 | } 50 | 51 | public function test_row_meta_filter_changed_for_plugin() { 52 | $links = array(); 53 | $plugin = $this->plugin_list_enhancer->get_plugin_basename(); 54 | 55 | $actual = $this->plugin_list_enhancer->insert_addon_store_link( $links, $plugin ); 56 | 57 | $this->assertcount( count( $links ) + 1, $actual ); 58 | } 59 | 60 | public function test_link_is_inserted() { 61 | $links = array(); 62 | 63 | $actual = $this->plugin_list_enhancer->insert_view_logs_link( $links ); 64 | 65 | $this->assertCount( count( $links ) + 2, $actual ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /codeception.yml: -------------------------------------------------------------------------------- 1 | actor: Tester 2 | paths: 3 | tests: tests 4 | log: tests/_output 5 | data: tests/_data 6 | helpers: tests/_support 7 | settings: 8 | bootstrap: _bootstrap.php 9 | colors: true 10 | memory_limit: 1024M 11 | modules: 12 | config: 13 | Db: 14 | dsn: 'mysql:host=localhost;dbname=wordpress-tests' 15 | user: root 16 | password: root 17 | dump: tests/_data/dump.sql 18 | WPBrowser: 19 | url: 'http://local.wordpress.dev' 20 | adminUsername: sudar 21 | adminPassword: localsudar 22 | adminUrl: /wp-admin 23 | WPDb: 24 | dsn: 'mysql:host=local.wordpress.dev;dbname=wordpress_default' 25 | user: external 26 | password: external 27 | dump: tests/_data/dump.sql 28 | populate: false 29 | cleanup: false 30 | url: 'http://local.wordpress.dev' 31 | tablePrefix: wp_ 32 | WPLoader: 33 | #wpRootFolder: /srv/www/wordpress-default/ 34 | wpRootFolder: /Users/sudar/dev/vvv/www/wordpress-default/ 35 | dbName: emaillog_test 36 | dbHost: local.wordpress.dev 37 | dbUser: external 38 | dbPassword: external 39 | wpDebug: true 40 | dbCharset: utf8 41 | dbCollate: '' 42 | tablePrefix: wptests_ 43 | domain: local.wordpress.dev 44 | adminEmail: admin@wp.local 45 | title: 'WP Tests' 46 | phpBinary: php 47 | language: '' 48 | plugins: [email-log/email-log.php] 49 | activatePlugins: [email-log/email-log.php] 50 | bootstrapActions: [] 51 | WPWebDriver: 52 | url: 'http://local.wordpress.dev' 53 | browser: phantomjs 54 | port: 4444 55 | restart: true 56 | wait: 2 57 | adminUsername: admin 58 | adminPassword: password 59 | adminUrl: /wp-admin 60 | -------------------------------------------------------------------------------- /tests/_support/_generated/IntegrationTesterActions.php: -------------------------------------------------------------------------------- 1 | getScenario()->runStep(new \Codeception\Step\Action('ensureDbModuleCompat', func_get_args())); 27 | } 28 | 29 | 30 | /** 31 | * [!] Method is generated. Documentation taken from corresponding module. 32 | * 33 | * Calls a list of user-defined actions needed in tests. 34 | * @see \Codeception\Module\WPLoader::bootstrapActions() 35 | */ 36 | public function bootstrapActions() { 37 | return $this->getScenario()->runStep(new \Codeception\Step\Action('bootstrapActions', func_get_args())); 38 | } 39 | 40 | 41 | /** 42 | * [!] Method is generated. Documentation taken from corresponding module. 43 | * 44 | * 45 | * @see \Codeception\Module\WPLoader::activatePlugins() 46 | */ 47 | public function activatePlugins() { 48 | return $this->getScenario()->runStep(new \Codeception\Step\Action('activatePlugins', func_get_args())); 49 | } 50 | 51 | 52 | /** 53 | * [!] Method is generated. Documentation taken from corresponding module. 54 | * 55 | * Loads the plugins required by the test. 56 | * @see \Codeception\Module\WPLoader::loadPlugins() 57 | */ 58 | public function loadPlugins() { 59 | return $this->getScenario()->runStep(new \Codeception\Step\Action('loadPlugins', func_get_args())); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /include/Addon/License/BundleLicense.php: -------------------------------------------------------------------------------- 1 | license_data ) ) { 33 | return parent::get_license_key(); 34 | } 35 | 36 | return $this->license_data->bundle_license_key; 37 | } 38 | 39 | /** 40 | * The option name in which the bundle license data will be stored. 41 | * 42 | * @return string Option name. 43 | */ 44 | protected function get_option_name() { 45 | return 'el_bundle_license'; 46 | } 47 | 48 | /** 49 | * Get the license key of an add-on from Bundle. 50 | * 51 | * @param string $addon_name Add-on name. 52 | * 53 | * @return bool|string False if no license key is found, otherwise license key. 54 | */ 55 | public function get_addon_license_key( $addon_name ) { 56 | if ( empty( $this->license_data ) ) { 57 | return false; 58 | } 59 | 60 | if ( ! isset( $this->license_data->bundled_licenses->{$addon_name} ) ) { 61 | return false; 62 | } 63 | 64 | return $this->license_data->bundled_licenses->{$addon_name}->license_key; 65 | } 66 | 67 | /** 68 | * Is the bundle license a lifetime license. 69 | * 70 | * @since 2.4.1 71 | * 72 | * @return bool True if it is a lifetime license, False otherwise. 73 | */ 74 | public function is_lifetime_license() { 75 | if ( empty( $this->license_data ) || ! isset( $this->license_data->expires ) ) { 76 | return false; 77 | } 78 | 79 | return ( false === $this->license_data->expires ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /tests/wp-tests/uninstall/UninstallWithDeleteTest.php: -------------------------------------------------------------------------------- 1 | plugin_file = 'email-log/email-log.php'; 25 | 26 | parent::setUp(); 27 | } 28 | 29 | /** 30 | * Test installation and uninstallation with deleting table. 31 | */ 32 | public function test_uninstall_with_deleting_table() { 33 | global $wpdb; 34 | 35 | /* 36 | * First test that the plugin installed itself properly. 37 | */ 38 | 39 | // Check that a database table was added. 40 | $this->assertTableExists( $wpdb->prefix . 'email_log' ); 41 | 42 | // Check that an option was added to the database. 43 | $this->assertEquals( '0.3', get_option( 'email-log-db' ) ); 44 | 45 | // add the option that will delete the table during uninstall. 46 | $value = array( 47 | 'allowed_user_roles' => array(), 48 | 'remove_on_uninstall' => 'true', 49 | ); 50 | update_option( 'email-log-core', $value ); 51 | 52 | $this->uninstall(); 53 | 54 | // Check that the table was deleted. 55 | $this->assertTableNotExists( $wpdb->prefix . 'email_log' ); 56 | 57 | // Check that all options with a prefix was deleted. 58 | $this->assertNoOptionsWithPrefix( 'email-log' ); 59 | 60 | // check the capability has been removed from all user roles. 61 | $roles = get_editable_roles(); 62 | foreach ( $roles as $role_name => $role_obj ) { 63 | $role = get_role( $role_name ); 64 | 65 | if ( ! is_null( $role ) ) { 66 | $this->assertFalse( $role->has_cap( 'manage_email_logs' ), 'Capability is not cleaned up' ); 67 | } 68 | } 69 | 70 | // check whether the license options got deleted. 71 | $this->assertNoOptionsWithPrefix( 'el_bundle_license' ); 72 | $this->assertNoOptionsWithPrefix( 'el_license_' ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /uninstall.php: -------------------------------------------------------------------------------- 1 | blog_id ); 20 | email_log_delete_db_data(); 21 | restore_current_blog(); 22 | } 23 | } else { 24 | email_log_delete_db_data(); 25 | } 26 | 27 | /** 28 | * Delete all email log data from db. 29 | * 30 | * The data include email log table, options, capability and add-on license data. 31 | * 32 | * @since 1.7 33 | * 34 | * @global object $wpdb 35 | */ 36 | function email_log_delete_db_data() { 37 | global $wpdb; 38 | 39 | $remove_data_on_uninstall = false; 40 | 41 | $option = get_option( 'email-log-core' ); 42 | if ( is_array( $option ) && array_key_exists( 'remove_on_uninstall', $option ) && 43 | 'true' === strtolower( $option['remove_on_uninstall'] ) ) { 44 | 45 | $remove_data_on_uninstall = true; 46 | } 47 | 48 | // This is hardcoded on purpose, since the entire plugin is not loaded during uninstall. 49 | $table_name = $wpdb->prefix . 'email_log'; 50 | 51 | if ( $remove_data_on_uninstall ) { 52 | if ( $wpdb->get_var( "SHOW TABLES LIKE '{$table_name}'" ) == $table_name ) { 53 | $wpdb->query( "DROP TABLE $table_name" ); 54 | } 55 | 56 | delete_option( 'email-log-db' ); 57 | delete_option( 'email-log-core' ); 58 | 59 | $roles = get_editable_roles(); 60 | foreach ( $roles as $role_name => $role_obj ) { 61 | $role = get_role( $role_name ); 62 | 63 | if ( ! is_null( $role ) ) { 64 | $role->remove_cap( 'manage_email_logs' ); 65 | } 66 | } 67 | // Mask Fields addon adds this option. 68 | delete_option( 'el_mask_fields' ); 69 | 70 | delete_option( 'el_bundle_license' ); 71 | $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'el_license_%'" ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: none 2 | 3 | enabled: 4 | - align_double_arrow 5 | - align_equals 6 | - align_phpdoc 7 | - alpha_ordered_imports 8 | - binary_operator_spaces 9 | - blank_line_after_namespace 10 | - blank_line_before_continue 11 | - blank_line_before_return 12 | - blank_line_before_throw 13 | - blank_line_before_try 14 | - cast_spaces 15 | - combine_consecutive_unsets 16 | - concat_with_spaces 17 | - elseif 18 | - encoding 19 | - function_typehint_space 20 | - hash_to_slash_comment 21 | - include 22 | - lowercase_cast 23 | - lowercase_constants 24 | - lowercase_keywords 25 | - method_visibility_required 26 | - native_function_casing 27 | - no_blank_lines_after_phpdoc 28 | - no_blank_lines_after_return 29 | - no_blank_lines_after_throw 30 | - no_closing_tag 31 | - no_empty_comment 32 | - no_empty_phpdoc 33 | - no_empty_statement 34 | - no_extra_consecutive_blank_lines 35 | - no_leading_namespace_whitespace 36 | - no_short_echo_tag 37 | - no_spaces_after_function_name 38 | - no_trailing_comma_in_list_call 39 | - no_trailing_comma_in_singleline_array 40 | - no_trailing_whitespace 41 | - no_trailing_whitespace_in_comment 42 | - no_unused_imports 43 | - no_whitespace_before_comma_in_array 44 | - no_whitespace_in_blank_line 45 | - not_operator_with_space 46 | - phpdoc_add_missing_param_annotation 47 | - phpdoc_align 48 | - phpdoc_indent 49 | - phpdoc_no_package 50 | - phpdoc_no_useless_inheritdoc 51 | - phpdoc_order 52 | - phpdoc_scalar 53 | - phpdoc_separation 54 | - phpdoc_single_line_var_spacing 55 | - phpdoc_summary 56 | - phpdoc_types 57 | - phpdoc_types_order 58 | - phpdoc_var_without_name 59 | - property_visibility_required 60 | - return_type_declaration 61 | - short_scalar_cast 62 | - single_blank_line_at_eof 63 | - single_class_element_per_statement 64 | - single_import_per_statement 65 | - single_line_after_imports 66 | - single_quote 67 | - standardize_not_equals 68 | - switch_case_semicolon_to_colon 69 | - ternary_operator_spaces 70 | - trailing_comma_in_multiline_array 71 | - unix_line_endings 72 | - whitespace_after_comma_in_array 73 | 74 | finder: 75 | not-path: 76 | - "libraries" 77 | exclude: 78 | - "tests" 79 | name: 80 | - "*.php" 81 | not-name: 82 | - "EmailLogger.php" 83 | -------------------------------------------------------------------------------- /include/Core/UI/Page/AddonListPage.php: -------------------------------------------------------------------------------- 1 | page = add_submenu_page( 22 | LogListPage::PAGE_SLUG, 23 | __( 'Add-ons', 'email-log' ), 24 | __( 'Add-ons', 'email-log' ), 25 | 'manage_options', 26 | self::PAGE_SLUG, 27 | array( $this, 'render_page' ) 28 | ); 29 | 30 | add_action( "load-{$this->page}", array( $this, 'render_help_tab' ) ); 31 | add_action( "load-{$this->page}", array( $this, 'enqueue_assets' ) ); 32 | } 33 | 34 | /** 35 | * Render the list of add-on in the page. 36 | */ 37 | public function render_page() { 38 | ?> 39 |
40 |

41 | 42 | 43 |

44 | 45 | 46 |

47 | 48 | get_licenser(); 58 | if ( ! is_null( $licenser ) ) { 59 | $licenser->get_addon_list()->render(); 60 | } 61 | ?> 62 |
63 | render_page_footer(); 66 | } 67 | 68 | /** 69 | * Enqueue static assets needed for this page. 70 | */ 71 | public function enqueue_assets() { 72 | $email_log = email_log(); 73 | 74 | wp_enqueue_style( 'el_addon_list', plugins_url( 'assets/css/admin/addon-list.css', $email_log->get_plugin_file() ), array(), $email_log->get_version() ); 75 | wp_enqueue_script( 'el_addon_list', plugins_url( 'assets/js/admin/addon-list.js', $email_log->get_plugin_file() ), array( 'jquery' ), $email_log->get_version(), true ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /include/Core/UI/UILoader.php: -------------------------------------------------------------------------------- 1 | initialize_components(); 37 | $this->initialize_pages(); 38 | 39 | foreach ( $this->components as $component ) { 40 | $component->load(); 41 | } 42 | 43 | foreach ( $this->pages as $page ) { 44 | $page->load(); 45 | } 46 | } 47 | 48 | public function is_show_dashboard_widget() { 49 | $this->components['core_settings'] = new Setting\CoreSetting(); 50 | $dashboard_status = false; 51 | $options = get_option( 'email-log-core' ); 52 | if( isset( $options['hide_dashboard_widget'] ) ) { 53 | $dashboard_status = $options['hide_dashboard_widget']; 54 | } 55 | 56 | return $dashboard_status; 57 | } 58 | 59 | /** 60 | * Initialize UI component Objects. 61 | * 62 | * This method may be overwritten in tests. 63 | * 64 | * @access protected 65 | */ 66 | protected function initialize_components() { 67 | if ( current_user_can( LogListPage::CAPABILITY ) ) { 68 | $this->components['admin_ui_enhancer'] = new Component\AdminUIEnhancer(); 69 | if( ! $this->is_show_dashboard_widget() ) { 70 | $this->components['dashboard_widget'] = new Component\DashboardWidget(); 71 | } 72 | } 73 | } 74 | 75 | /** 76 | * Initialize Admin page Objects. 77 | * 78 | * This method may be overwritten in tests. 79 | * 80 | * @access protected 81 | */ 82 | protected function initialize_pages() { 83 | $this->pages['log_list_page'] = new Page\LogListPage(); 84 | $this->pages['settings_page'] = new Page\SettingsPage(); 85 | $this->pages['addon_list_page'] = new Page\AddonListPage(); 86 | $this->pages['system_info_page'] = new Page\SystemInfoPage(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* global module, require */ 2 | module.exports = function( grunt ) { 3 | 'use strict'; 4 | 5 | // Load all grunt tasks 6 | require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); 7 | 8 | // Project configuration 9 | grunt.initConfig( { 10 | pkg: grunt.file.readJSON( 'package.json' ), 11 | 12 | clean : { 13 | dist: ['dist/'] 14 | }, 15 | 16 | copy: { 17 | dist: { 18 | files : [ 19 | { 20 | expand: true, 21 | src: [ 22 | '**', 23 | '!dist/**', 24 | '!assets-wp-repo/**', 25 | '!code-coverage/**', 26 | '!codeception.yml', 27 | '!node_modules/**', 28 | '!assets/vendor/**', 29 | 'assets/vendor/insertion-query/insQ.min.js', 30 | 'assets/vendor/jquery-ui/themes/base/jquery-ui.min.css', 31 | '!assets/js/src/**', 32 | '!assets/css/src/**', 33 | '!Gruntfile.js', 34 | '!bower.json', 35 | '!package.json', 36 | '!package-lock.json', 37 | '!composer.json', 38 | '!composer.lock', 39 | '!phpcs.xml', 40 | '!phpdoc.dist.xml', 41 | '!phpunit.xml.dist', 42 | '!bin/**', 43 | '!tests/**', 44 | '!.idea/**', 45 | '!tags', 46 | '!vendor/**', 47 | "vendor/sudar/wp-system-info/**", 48 | "vendor/collizo4sky/persist-admin-notices-dismissal/**" 49 | ], 50 | dest: 'dist/' 51 | } 52 | ] 53 | }, 54 | jqueryUi: { 55 | files: [ 56 | { 57 | src : "node_modules/components-jqueryui/themes/base/jquery-ui.min.css", 58 | dest: "assets/vendor/jquery-ui/themes/base/jquery-ui.min.css" 59 | }, 60 | { 61 | expand: true, 62 | src: ["node_modules/components-jqueryui/themes/base/images/*"], 63 | dest: "assets/vendor/jquery-ui/themes/base/images/", 64 | flatten: true, 65 | filter: "isFile" 66 | } 67 | ] 68 | }, 69 | insertionQ: { 70 | files: [ 71 | { 72 | src : "node_modules/insertion-query/insQ.min.js", 73 | dest: "assets/vendor/insertion-query/insQ.min.js" 74 | } 75 | ] 76 | }, 77 | }, 78 | 79 | makepot: { 80 | target: { 81 | options: { 82 | exclude: ['vendor/.*', 'dist/.*'], 83 | updateTimestamp: false, 84 | } 85 | } 86 | }, 87 | 88 | watch: { 89 | all: { 90 | files: ['**', '!dist/**'], 91 | tasks: ['build'] 92 | } 93 | } 94 | } ); 95 | 96 | require('time-grunt')(grunt); 97 | 98 | grunt.registerTask("vendor", ["copy:jqueryUi", "copy:insertionQ"]); 99 | grunt.registerTask("build", ["vendor", "clean", "copy:dist"]); 100 | 101 | grunt.util.linefeed = '\n'; 102 | }; 103 | -------------------------------------------------------------------------------- /include/Core/Request/OverridePluginAPI.php: -------------------------------------------------------------------------------- 1 | get_licenser(); 34 | 35 | if ( is_null( $licenser ) ) { 36 | return; 37 | } 38 | 39 | $inactive_addons = $licenser->get_addon_list()->get_inactive_addons(); 40 | 41 | foreach ( $inactive_addons as $inactive_addon ) { 42 | $license_key = $licenser->get_addon_license_key( $inactive_addon->name ); 43 | 44 | $updater = new EDDUpdater( 45 | $email_log->get_store_url(), 46 | $inactive_addon->file, 47 | array( 48 | 'version' => $inactive_addon->get_version(), 49 | 'license' => $license_key, 50 | 'item_name' => $inactive_addon->name, 51 | 'author' => $inactive_addon->author, 52 | ) 53 | ); 54 | 55 | $licenser->add_updater( $updater ); 56 | } 57 | } 58 | 59 | /** 60 | * Add version attribute to plugin API response. 61 | * 62 | * The API response generated by EDD doesn't have the version attribute and it results in some warnings. 63 | * This method fixes it by manually adding the version attribute to the API response. 64 | * 65 | * @since 2.1.0 66 | * 67 | * @param object $response API Response. 68 | * @param string $action Action name. 69 | * @param array $args Arguments for the function. 70 | * 71 | * @return object Modified API response. 72 | */ 73 | public function add_version_to_plugin_api_response( $response, $action, $args ) { 74 | if ( 'plugin_information' !== $action ) { 75 | return $response; 76 | } 77 | 78 | if ( ! isset( $args->slug ) || ( substr( $args->slug, 0, 10 ) != 'email-log-' ) ) { 79 | return $response; 80 | } 81 | 82 | if ( isset( $response->version ) ) { 83 | return $response; 84 | } 85 | 86 | if ( ! isset( $response->new_version ) ) { 87 | return $response; 88 | } 89 | 90 | $response->version = $response->new_version; 91 | 92 | return $response; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /email-log.php: -------------------------------------------------------------------------------- 1 | 47 |
48 |

49 | v1.9.1 of Email Log.', 'email-log' ), // @codingStandardsIgnoreLine 52 | 'https://downloads.wordpress.org/plugin/email-log.1.9.1.zip' 53 | ); 54 | ?> 55 |

56 |
57 | parse( $headers ); 61 | } 62 | 63 | /** 64 | * Parse Headers. 65 | * 66 | * @access private 67 | * 68 | * @param string $headers Headers to be parsed. 69 | * 70 | * @return array Parsed headers. 71 | */ 72 | private function parse( $headers ) { 73 | $data = array(); 74 | $arr_headers = explode( "\n", $headers ); 75 | 76 | foreach ( $arr_headers as $header ) { 77 | $split_header = explode( ':', $header ); 78 | $value = $this->parse_header_line( $split_header ); 79 | 80 | if ( trim( $value ) != '' ) { 81 | switch ( strtolower( $split_header[0] ) ) { 82 | case 'from': 83 | $data['from'] = $value; 84 | break; 85 | 86 | case 'cc': 87 | $data['cc'] = $value; 88 | break; 89 | 90 | case 'bcc': 91 | $data['bcc'] = $value; 92 | break; 93 | 94 | case 'reply-to': 95 | $data['reply_to'] = $value; 96 | break; 97 | 98 | case 'content-type': 99 | $data['content_type'] = $value; 100 | break; 101 | } 102 | } 103 | } 104 | 105 | return $data; 106 | } 107 | 108 | /** 109 | * Parse individual header line. 110 | * 111 | * @since 1.0 112 | * @access private 113 | * 114 | * @param array $header Header line to be parsed. 115 | * 116 | * @return string Parsed value. 117 | */ 118 | private function parse_header_line( $header ) { 119 | $value = ''; 120 | if ( 2 == count( $header ) ) { 121 | if ( is_array( $header[1] ) ) { 122 | $value = trim( implode( ',', array_map( 'trim', $header[1] ) ) ); 123 | } else { 124 | $value = trim( $header[1] ); 125 | } 126 | } 127 | 128 | return $value; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /load-email-log.php: -------------------------------------------------------------------------------- 1 | add_namespace( 'EmailLog', $plugin_dir . 'include' ); 29 | $loader->add_namespace( 'Sudar\\WPSystemInfo', $plugin_dir . 'vendor/sudar/wp-system-info/src/' ); 30 | 31 | if ( file_exists( $plugin_dir . 'tests/' ) ) { 32 | // if tests are present, then add them. 33 | $loader->add_namespace( 'EmailLog', $plugin_dir . 'tests/wp-tests' ); 34 | } 35 | 36 | $loader->add_file( $plugin_dir . 'include/Util/helper.php' ); 37 | $loader->add_file( $plugin_dir . 'include/Addon/addon-helper.php' ); 38 | $loader->add_file( $plugin_dir . 'vendor/collizo4sky/persist-admin-notices-dismissal/persist-admin-notices-dismissal.php' ); 39 | 40 | $loader->register(); 41 | 42 | $email_log = new \EmailLog\Core\EmailLog( $plugin_file, $loader, new \EmailLog\Core\DB\TableManager() ); 43 | 44 | if ( \EmailLog\Util\is_admin_non_ajax_request() ) { 45 | // Loading licenser in frontend or ajax request is resulting in huge performance issues. 46 | $email_log->set_licenser( new \EmailLog\Addon\License\Licenser() ); 47 | 48 | $email_log->add_loadie( new \EmailLog\Addon\Upseller() ); 49 | $email_log->add_loadie( new \EmailLog\Addon\DependencyEnforcer() ); 50 | } 51 | 52 | $email_log->add_loadie( new \EmailLog\Core\EmailLogger() ); 53 | $email_log->add_loadie( new \EmailLog\Core\UI\UILoader() ); 54 | 55 | $email_log->add_loadie( new \EmailLog\Core\Request\NonceChecker() ); 56 | $email_log->add_loadie( new \EmailLog\Core\Request\LogListAction() ); 57 | 58 | $capability_giver = new \EmailLog\Core\AdminCapabilityGiver(); 59 | $email_log->add_loadie( $capability_giver ); 60 | 61 | // `register_activation_hook` can't be called from inside any hook. 62 | register_activation_hook( $plugin_file, array( $email_log->table_manager, 'on_activate' ) ); 63 | register_activation_hook( $plugin_file, array( $capability_giver, 'add_cap_to_admin' ) ); 64 | 65 | // Ideally the plugin should be loaded in a later event like `init` or `wp_loaded`. 66 | // But some plugins like EDD are sending emails in `init` event itself, 67 | // which won't be logged if the plugin is loaded in `wp_loaded` or `init`. 68 | add_action( 'plugins_loaded', array( $email_log, 'load' ), 101 ); 69 | } 70 | 71 | /** 72 | * Return the global instance of Email Log plugin. 73 | * Eventually the EmailLog class might become singleton. 74 | * 75 | * @since 2.0 76 | * 77 | * @global \EmailLog\Core\EmailLog $email_log 78 | * 79 | * @return \EmailLog\Core\EmailLog 80 | */ 81 | function email_log() { 82 | global $email_log; 83 | 84 | return $email_log; 85 | } 86 | -------------------------------------------------------------------------------- /include/Core/UI/Page/SystemInfoPage.php: -------------------------------------------------------------------------------- 1 | system_info = new EmailLogSystemInfo( 'email-log' ); 35 | $this->system_info->load(); 36 | } 37 | 38 | public function register_page() { 39 | $this->page = add_submenu_page( 40 | LogListPage::PAGE_SLUG, 41 | __( 'System Info', 'email-log' ), 42 | __( 'System Info', 'email-log' ), 43 | self::CAPABILITY, 44 | self::PAGE_SLUG, 45 | array( $this, 'render_page' ) 46 | ); 47 | 48 | add_action( "load-{$this->page}", array( $this, 'render_help_tab' ) ); 49 | 50 | /** 51 | * Fires before loading Sytem Info page. 52 | * 53 | * @since 2.3.0 54 | * 55 | * @param string $page Page slug. 56 | */ 57 | do_action( 'el_load_system_info_page', $this->page ); 58 | } 59 | 60 | /** 61 | * Render the page. 62 | */ 63 | public function render_page() { 64 | ?> 65 | 66 |
67 |
68 |

69 | 70 | 71 | 72 |

73 |
74 | 75 | 76 |
77 |

78 | enabled. This prevents scheduler from running.', 'email-log' ), 'https://codex.wordpress.org/Editing_wp-config.php#Disable_Cron_and_Cron_Timeout' ); ?> 79 |

80 |
81 | 82 | 83 |
84 |

85 | 86 | system_info->render(); 88 | ?> 89 | 90 |

91 | 92 | 96 |

97 |
98 |
99 | 100 | render_page_footer(); 102 | } 103 | 104 | /** 105 | * Download System info file. 106 | */ 107 | public function download_system_info() { 108 | $this->system_info->download_as_file(); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /include/Addon/DependencyEnforcer.php: -------------------------------------------------------------------------------- 1 | '2.0', 20 | 'email-log-more-fields/email-log-more-fields.php' => '2.0', 21 | 'email-log-resend-email/email-log-resend-email.php' => '2.0', 22 | ); 23 | 24 | /** 25 | * Setup action and hooks. 26 | */ 27 | public function load() { 28 | // TODO: Ideally, this should not be called on all admin pages. 29 | add_action( 'admin_notices', array( $this, 'render_compatibility_notice' ) ); 30 | } 31 | 32 | /** 33 | * Render compatibility notice, if needed. 34 | * TODO: Include link to the add-on store in the admin notice. 35 | */ 36 | public function render_compatibility_notice() { 37 | $deactivated_addons = $this->deactivate_outdated_active_addons(); 38 | 39 | if ( empty( $deactivated_addons ) ) { 40 | return; 41 | } 42 | 43 | ?> 44 |
45 |

46 | 47 |

54 | 55 |

56 |
57 | get_outdated_active_addons(); 71 | foreach ( $outdated_active_addons as $addon_file_name => $outdated_active_addon ) { 72 | deactivate_plugins( plugin_basename( $addon_file_name ) ); 73 | $deactivated_active_addons[] = $outdated_active_addon['Name'] . ' ' . $outdated_active_addon['Version']; 74 | } 75 | 76 | return $deactivated_active_addons; 77 | } 78 | 79 | /** 80 | * Get the list of add-ons that are outdated and are active. 81 | * 82 | * @access private 83 | * 84 | * @return array List of outdated and active add-ons. 85 | */ 86 | private function get_outdated_active_addons() { 87 | $outdated_active_addons = array(); 88 | $plugins = get_plugins(); 89 | 90 | foreach ( $this->addon_dependency_map as $addon => $required_version ) { 91 | if ( is_plugin_active( $addon ) ) { 92 | $active_addon = $plugins[ $addon ]; 93 | 94 | if ( version_compare( $active_addon['Version'], $required_version, '<' ) ) { 95 | $outdated_active_addons[ $addon ] = $active_addon; 96 | } 97 | } 98 | } 99 | 100 | return $outdated_active_addons; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /include/Addon/API/EDDUpdater.php: -------------------------------------------------------------------------------- 1 | get_plugin_path() . 'include/libraries/EDD_SL_Plugin_Updater.php'; 8 | } 9 | 10 | /** 11 | * Update add-on using EDD API. 12 | * 13 | * @since 2.0.0 14 | */ 15 | class EDDUpdater extends \EDD_SL_Plugin_Updater { 16 | 17 | /** 18 | * The name part of the add-on file without .php extension. 19 | * 20 | * The base class already has a slug property but it is private. 21 | * So we have to create a duplicate to handle that. 22 | * 23 | * @var string 24 | */ 25 | protected $addon_slug; 26 | 27 | /** 28 | * Directory and filename of the add-on. 29 | * 30 | * The base class already has a slug property but it is private. 31 | * So we have to create a duplicate to handle that. 32 | * 33 | * @since 2.2.4 34 | * 35 | * @var string 36 | */ 37 | protected $addon_name; 38 | 39 | /** 40 | * Extract add-on slug alone and then pass everything to parent. 41 | * 42 | * @param string $_api_url The URL pointing to the custom API endpoint. 43 | * @param string $_plugin_file Path to the plugin file. 44 | * @param array|null $_api_data Optional data to send with API calls. 45 | */ 46 | public function __construct( $_api_url, $_plugin_file, $_api_data = null ) { 47 | $this->addon_slug = basename( $_plugin_file, '.php' ); 48 | $this->addon_name = plugin_basename( $_plugin_file ); 49 | 50 | parent::__construct( $_api_url, $_plugin_file, $_api_data ); 51 | } 52 | 53 | /** 54 | * Overridden to disable `check_update` on the add-ons that are not installed. 55 | * 56 | * @inheritdoc 57 | * 58 | * @since 2.2.0 59 | */ 60 | public function init() { 61 | parent::init(); 62 | 63 | $installed_plugins = array_keys( get_plugins() ); 64 | 65 | if ( in_array( $this->get_name(), $installed_plugins, true ) ) { 66 | return; 67 | } 68 | 69 | remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) ); 70 | } 71 | 72 | /** 73 | * Get add-on slug. 74 | * 75 | * The name part of the add-on file without .php extension. 76 | * 77 | * @return string Add-on slug. 78 | */ 79 | public function get_slug() { 80 | return $this->addon_slug; 81 | } 82 | 83 | /** 84 | * Get the add-on name. 85 | * 86 | * Directory and filename of the add-on. 87 | * 88 | * @since 2.2.4 89 | * 90 | * @return string Add-on name. 91 | */ 92 | public function get_name() { 93 | return $this->addon_name; 94 | } 95 | 96 | /** 97 | * Get Download URL. 98 | * 99 | * We can't call `api_request` method directly since it is declared as private in parent class. 100 | * So we call the `plugins_api_filter` method instead. 101 | * 102 | * @return string Download url. 103 | */ 104 | public function get_download_url() { 105 | $args = new \stdClass(); 106 | $args->slug = $this->get_slug(); 107 | 108 | $response = $this->plugins_api_filter( null, 'plugin_information', $args ); 109 | 110 | if ( ! $response instanceof \stdClass || ! property_exists( $response, 'package' ) ) { 111 | return ''; 112 | } 113 | 114 | return $response->package; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /include/Core/UI/Page/SettingsPage.php: -------------------------------------------------------------------------------- 1 | get_setting_sections(); 34 | 35 | foreach ( $sections as $section ) { 36 | register_setting( 37 | self::PAGE_SLUG, 38 | $section->option_name, 39 | array( 'sanitize_callback' => $section->sanitize_callback ) 40 | ); 41 | 42 | add_settings_section( 43 | $section->id, 44 | $section->title, 45 | $section->callback, 46 | self::PAGE_SLUG 47 | ); 48 | 49 | foreach ( $section->fields as $field ) { 50 | add_settings_field( 51 | $section->id . '[' . $field->id . ']', 52 | $field->title, 53 | $field->callback, 54 | self::PAGE_SLUG, 55 | $section->id, 56 | $field->args 57 | ); 58 | } 59 | } 60 | } 61 | 62 | /** 63 | * Get a list of setting sections defined. 64 | * An add-on can define a setting section. 65 | * 66 | * @return \EmailLog\Core\UI\Setting\SettingSection[] List of defined setting sections. 67 | */ 68 | protected function get_setting_sections() { 69 | /** 70 | * Specify the list of setting sections in the settings page. 71 | * An add-on can add its own setting section by adding an instance of 72 | * SectionSection to the array. 73 | * 74 | * @since 2.0.0 75 | * 76 | * @param \EmailLog\Core\UI\Setting\SettingSection[] List of SettingSections. 77 | */ 78 | return apply_filters( 'el_setting_sections', array() ); 79 | } 80 | 81 | /** 82 | * Register page. 83 | */ 84 | public function register_page() { 85 | 86 | $sections = $this->get_setting_sections(); 87 | 88 | if ( empty( $sections ) ) { 89 | return; 90 | } 91 | 92 | $this->page = add_submenu_page( 93 | LogListPage::PAGE_SLUG, 94 | __( 'Settings', 'email-log' ), 95 | __( 'Settings', 'email-log' ), 96 | 'manage_options', 97 | self::PAGE_SLUG, 98 | array( $this, 'render_page' ) 99 | ); 100 | 101 | add_action( "load-{$this->page}", array( $this, 'render_help_tab' ) ); 102 | } 103 | 104 | /** 105 | * Render the page. 106 | * //TODO: Convert these sections into tabs. 107 | */ 108 | public function render_page() { 109 | ?> 110 |
111 |

112 | 113 |
114 | 121 |
122 | 123 |
124 | render_page_footer(); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /tests/wp-tests/EmailLogAutoloaderTest.php: -------------------------------------------------------------------------------- 1 | class_files = $class_files; 16 | } 17 | 18 | protected function require_file( $file ) { 19 | return in_array( $file, $this->class_files ); 20 | } 21 | 22 | public function get_files() { 23 | return $this->files; 24 | } 25 | } 26 | 27 | /** 28 | * Test Autoloader 29 | * @package EmailLog 30 | */ 31 | class EmailLogAutoloaderTest extends \PHPUnit_Framework_TestCase { 32 | protected $loader; 33 | 34 | protected function setUp() { 35 | $this->loader = new MockEmailLogAutoloaderClass; 36 | 37 | $this->loader->set_class_files( array( 38 | '/vendor/foo.bar/src/ClassName.php', 39 | '/vendor/foo.bar/src/DoomClassName.php', 40 | '/vendor/foo.bar/tests/ClassNameTest.php', 41 | '/vendor/foo.bardoom/src/ClassName.php', 42 | '/vendor/foo.bar.baz.dib/src/ClassName.php', 43 | '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php', 44 | ) ); 45 | 46 | $this->loader->add_namespace( 47 | 'Foo\Bar', 48 | '/vendor/foo.bar/src' 49 | ); 50 | 51 | $this->loader->add_namespace( 52 | 'Foo\Bar', 53 | '/vendor/foo.bar/tests' 54 | ); 55 | 56 | $this->loader->add_namespace( 57 | 'Foo\BarDoom', 58 | '/vendor/foo.bardoom/src' 59 | ); 60 | 61 | $this->loader->add_namespace( 62 | 'Foo\Bar\Baz\Dib', 63 | '/vendor/foo.bar.baz.dib/src' 64 | ); 65 | 66 | $this->loader->add_namespace( 67 | 'Foo\Bar\Baz\Dib\Zim\Gir', 68 | '/vendor/foo.bar.baz.dib.zim.gir/src' 69 | ); 70 | } 71 | 72 | public function testExistingFile() { 73 | $actual = $this->loader->load_class( 'Foo\Bar\ClassName' ); 74 | $expect = '/vendor/foo.bar/src/ClassName.php'; 75 | $this->assertSame( $expect, $actual ); 76 | 77 | $actual = $this->loader->load_class( 'Foo\Bar\ClassNameTest' ); 78 | $expect = '/vendor/foo.bar/tests/ClassNameTest.php'; 79 | $this->assertSame( $expect, $actual ); 80 | } 81 | 82 | public function testMissingFile() { 83 | $actual = $this->loader->load_class( 'No_Vendor\No_Package\NoClass' ); 84 | $this->assertFalse( $actual ); 85 | } 86 | 87 | public function testDeepFile() { 88 | $actual = $this->loader->load_class( 'Foo\Bar\Baz\Dib\Zim\Gir\ClassName' ); 89 | $expect = '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php'; 90 | $this->assertSame( $expect, $actual ); 91 | } 92 | 93 | public function testConfusion() { 94 | $actual = $this->loader->load_class( 'Foo\Bar\DoomClassName' ); 95 | $expect = '/vendor/foo.bar/src/DoomClassName.php'; 96 | $this->assertSame( $expect, $actual ); 97 | 98 | $actual = $this->loader->load_class( 'Foo\BarDoom\ClassName' ); 99 | $expect = '/vendor/foo.bardoom/src/ClassName.php'; 100 | $this->assertSame( $expect, $actual ); 101 | } 102 | 103 | public function testFileIsAdded() { 104 | $file_name = 'path/to/some/file'; 105 | $this->loader->add_file( $file_name ); 106 | 107 | $actual = in_array( $file_name, $this->loader->get_files() ); 108 | 109 | $this->assertTrue( $actual ); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /include/Core/Request/NonceChecker.php: -------------------------------------------------------------------------------- 1 | Bulk actions from the top dropdown. 31 | * action2 => Bulk actions from the bottom dropdown. 32 | */ 33 | public function check_nonce() { 34 | if ( ! isset( $_POST['el-action'] ) && ! isset( $_REQUEST['action'] ) && ! isset( $_REQUEST['action2'] ) ) { 35 | return; 36 | } 37 | 38 | if ( isset( $_POST['el-action'] ) ) { 39 | $action = sanitize_text_field( $_POST['el-action'] ); 40 | 41 | $allowed_actions = [ 42 | 'el-download-system-info', 43 | 'el_license_activate', 44 | 'el_license_deactivate', 45 | 'el_bundle_license_activate', 46 | 'el_bundle_license_deactivate', 47 | 'el-log-list-export', 48 | 'el-log-list-export-all', 49 | 'el-export-logs-with-columns' 50 | ]; 51 | 52 | if ( ! in_array( $action, $allowed_actions ) ) { 53 | return; 54 | } 55 | 56 | if ( ! isset( $_POST[ $action . '_nonce' ] ) ) { 57 | return; 58 | } 59 | 60 | if ( ! wp_verify_nonce( $_POST[ $action . '_nonce' ], $action ) ) { 61 | return; 62 | } 63 | } 64 | 65 | if ( isset( $_REQUEST['action'] ) || isset( $_REQUEST['action2'] ) ) { 66 | $action = sanitize_text_field( $_REQUEST['action'] ); 67 | 68 | if ( '-1' === $action ) { 69 | if ( ! isset( $_REQUEST['action2'] ) ) { 70 | return; 71 | } 72 | 73 | $action = sanitize_text_field( $_REQUEST['action2'] ); 74 | } 75 | 76 | if ( strpos( $action, 'el-log-list-' ) !== 0 && strpos( $action, 'el-cron-' ) !== 0 ) { 77 | return; 78 | } 79 | 80 | if ( strpos( $action, 'el-log-list-' ) === 0 ) { 81 | if ( ! isset( $_REQUEST[ LogListPage::LOG_LIST_ACTION_NONCE_FIELD ] ) ) { 82 | return; 83 | } 84 | 85 | if ( ! wp_verify_nonce( $_REQUEST[ LogListPage::LOG_LIST_ACTION_NONCE_FIELD ], LogListPage::LOG_LIST_ACTION_NONCE ) ) { 86 | return; 87 | } 88 | } 89 | 90 | if ( strpos( $action, 'el-cron-' ) === 0 ) { 91 | if ( ! isset( $_REQUEST[ $action . '-nonce-field' ] ) ) { 92 | return; 93 | } 94 | 95 | if ( ! wp_verify_nonce( $_REQUEST[ $action . '-nonce-field' ], $action . '-nonce' ) ) { 96 | return; 97 | } 98 | } 99 | } 100 | 101 | /** 102 | * Perform `el` action. 103 | * Nonce check has already happened at this point. 104 | * 105 | * @since 2.0.0 106 | * 107 | * @param string $action Action name. 108 | * @param array $_REQUEST Request data. 109 | */ 110 | do_action( 'el_action', $action, $_REQUEST ); 111 | 112 | /** 113 | * Perform `el` action. 114 | * Nonce check has already happened at this point. 115 | * 116 | * @since 2.0.0 117 | * 118 | * @param array $_REQUEST Request data. 119 | */ 120 | do_action( $action, $_REQUEST ); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /include/Core/UI/Page/BasePage.php: -------------------------------------------------------------------------------- 1 | ' . 49 | __( 'Email Log is a WordPress plugin that allows you to easily log and view all emails sent from WordPress.', 'email-log' ) . 50 | '

' . 51 | '

' . 52 | __( 'You can view the logged emails from the View Logs screen. ', 'email-log' ) . 53 | sprintf( 54 | __( 'Check the documentation about the View Logs screen for more details.', 'email-log' ), 55 | 'https://wpemaillog.com/docs/view-logged-email/?utm_campaign=Upsell&utm_medium=wpadmin&utm_source=help&utm_content=docs-content' 56 | ) . 57 | '

' . 58 | '

' . 59 | sprintf( 60 | __( 'You can perform advanced actions like re-sending email, automatically forwarding emails or export logs with our premium plugins.', 'email-log' ), 61 | 'https://wpemaillog.com/store/?utm_campaign=Upsell&utm_medium=wpadmin&utm_source=help&utm_content=store-content' 62 | ) . 63 | '

'; 64 | 65 | $this->get_screen()->add_help_tab( 66 | array( 67 | 'title' => __( 'About Plugin', 'email-log' ), 68 | 'id' => 'about_tab', 69 | 'content' => $content, 70 | 'callback' => false, 71 | ) 72 | ); 73 | 74 | $this->get_screen()->set_help_sidebar( 75 | '

' . __( 'More information', 'email-log' ) . '

' . 76 | '

' . __( 'Documentation', 'email-log' ) . '

' . 77 | '

' . __( 'Support', 'email-log' ) . '

' . 78 | '

' . __( 'Add-ons', 'email-log' ) . '

' 79 | ); 80 | } 81 | 82 | /** 83 | * Render admin page footer. 84 | */ 85 | protected function render_page_footer() { 86 | /** 87 | * Action to add additional content to email log admin footer. 88 | * 89 | * @since 1.8 90 | */ 91 | do_action( 'el_admin_footer' ); 92 | } 93 | 94 | /** 95 | * Return the WP_Screen object for the current page's handle. 96 | * 97 | * @return \WP_Screen Screen object. 98 | */ 99 | public function get_screen() { 100 | if ( ! isset( $this->screen ) ) { 101 | $this->screen = \WP_Screen::get( $this->page ); 102 | } 103 | 104 | return $this->screen; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /include/Core/UI/Component/AdminUIEnhancer.php: -------------------------------------------------------------------------------- 1 | get_plugin_file(); 37 | } 38 | 39 | $this->plugin_file = $file; 40 | $this->plugin_basename = plugin_basename( $file ); 41 | } 42 | 43 | /** 44 | * Setup hooks. 45 | * 46 | * 47 | */ 48 | public function load() { 49 | add_filter( 'plugin_row_meta', array( $this, 'insert_addon_store_link' ), 10, 2 ); 50 | add_filter( 'plugin_action_links_' . $this->plugin_basename, array( $this, 'insert_view_logs_link' ) ); 51 | 52 | add_action( 'el_admin_footer', array( $this, 'hook_footer_links' ) ); 53 | } 54 | 55 | /** 56 | * Add link to Add-ons store. 57 | * 58 | * @see Additional links in the Plugin listing is based on 59 | * @link http://zourbuth.com/archives/751/creating-additional-wordpress-plugin-links-row-meta/ 60 | * 61 | * @param array $links Array with default links to display in plugins page. 62 | * @param string $file The name of the plugin file. 63 | * 64 | * @return array Modified list of links to display in plugins page. 65 | */ 66 | public function insert_addon_store_link( $links, $file ) { 67 | if ( $file === $this->plugin_basename ) { 68 | $links[] = '' . 69 | __( 'Buy Addons', 'email-log' ) . ''; 70 | } 71 | 72 | return $links; 73 | } 74 | 75 | /** 76 | * Add link to 'View logs' page in plugin listing page. 77 | * 78 | * @since 2.3.0 Added Settings link. 79 | * 80 | * @param array $links List of links. 81 | * 82 | * @return array Modified list of links. 83 | */ 84 | public function insert_view_logs_link( $links ) { 85 | $view_logs_link = '' . __( 'View Logs', 'email-log' ) . ''; 86 | $settings_link = '' . __( 'Settings', 'email-log' ) . ''; 87 | array_unshift( $links, $view_logs_link, $settings_link ); 88 | 89 | return $links; 90 | } 91 | 92 | /** 93 | * Hook Footer links. 94 | */ 95 | public function hook_footer_links() { 96 | add_action( 'in_admin_footer', array( $this, 'add_credit_links' ) ); 97 | } 98 | 99 | /** 100 | * Adds Footer links. 101 | * 102 | * @since Genesis 103 | * @see Function relied on 104 | * @link http://striderweb.com/nerdaphernalia/2008/06/give-your-wordpress-plugin-credit/ 105 | */ 106 | public function add_credit_links() { 107 | $plugin_data = get_plugin_data( $this->plugin_file ); 108 | printf( 109 | '%1$s ' . __( 'plugin', 'email-log' ) . ' | ' . __( 'Version', 'email-log' ) . ' %2$s | ' . __( 'by', 'email-log' ) . ' %3$s
', 110 | $plugin_data['Title'], 111 | $plugin_data['Version'], 112 | $plugin_data['Author'] 113 | ); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /include/Addon/API/EDDAPI.php: -------------------------------------------------------------------------------- 1 | get_store_url(); 30 | } 31 | 32 | $this->store_url = $store_url; 33 | } 34 | 35 | /** 36 | * Activate License. 37 | * 38 | * @param string $license_key License Key. 39 | * @param string $addon_name Add-on Name. 40 | * 41 | * @return object API Response JSON Object. 42 | */ 43 | public function activate_license( $license_key, $addon_name ) { 44 | $params = array( 45 | 'edd_action' => 'activate_license', 46 | 'license' => $license_key, 47 | 'item_name' => urlencode( $addon_name ), 48 | 'url' => home_url(), 49 | ); 50 | 51 | return $this->call_edd_api( $params ); 52 | } 53 | 54 | /** 55 | * Deactivate License. 56 | * 57 | * @param string $license_key License Key. 58 | * @param string $addon_name Add-on Name. 59 | * 60 | * @return object API Response JSON Object. 61 | */ 62 | public function deactivate_license( $license_key, $addon_name ) { 63 | $params = array( 64 | 'edd_action' => 'deactivate_license', 65 | 'license' => $license_key, 66 | 'item_name' => urlencode( $addon_name ), 67 | 'url' => home_url(), 68 | ); 69 | 70 | return $this->call_edd_api( $params ); 71 | } 72 | 73 | /** 74 | * Get version information. 75 | * 76 | * @param string $license_key License Key. 77 | * @param string $addon_name Add-on Name. 78 | * 79 | * @return object API Response JSON Object. 80 | */ 81 | public function get_version( $license_key, $addon_name ) { 82 | $params = array( 83 | 'edd_action' => 'get_version', 84 | 'license' => $license_key, 85 | 'item_name' => $addon_name, 86 | 'url' => home_url(), 87 | ); 88 | 89 | return $this->call_edd_api( $params ); 90 | } 91 | 92 | /** 93 | * Call the EDD API. 94 | * 95 | * @param array $params Parameters for request. 96 | * 97 | * @throws \Exception If there is any error while making the request. 98 | * 99 | * TODO: Make the errors more user friendly and provide links to support. 100 | * 101 | * @return object API Response in JSON. 102 | */ 103 | protected function call_edd_api( $params ) { 104 | $response = wp_remote_post( $this->store_url, array( 105 | 'timeout' => 15, 106 | 'body' => $params, 107 | ) ); 108 | 109 | if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { 110 | 111 | if ( is_wp_error( $response ) ) { 112 | throw new \Exception( $response->get_error_message() ); 113 | } 114 | 115 | throw new \Exception( __( 'Unknown error occurred while trying to contact Email Log store. Please try again after sometime. If the problem persists contact support.', 'email-log' ) ); 116 | } 117 | 118 | $body = wp_remote_retrieve_body( $response ); 119 | $data = json_decode( $body ); 120 | 121 | if ( empty( $data ) ) { 122 | throw new \Exception( __( 'Unable to parse the response Email Log store response. Please try again after sometime. If the problem persists contact support.', 'email-log' ) ); 123 | } 124 | 125 | return $data; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /include/Core/UI/Setting/Setting.php: -------------------------------------------------------------------------------- 1 | section = new SettingSection(); 24 | 25 | $this->initialize(); 26 | 27 | $this->section->fields = $this->get_fields(); 28 | $this->section->callback = array( $this, 'render' ); 29 | $this->section->sanitize_callback = array( $this, 'sanitize' ); 30 | } 31 | 32 | /** 33 | * Setup hooks and filters. 34 | */ 35 | public function load() { 36 | add_filter( 'el_setting_sections', array( $this, 'register' ) ); 37 | } 38 | 39 | /** 40 | * Register the setting using the filter. 41 | * 42 | * @param SettingSection[] $sections List of existing SettingSections. 43 | * 44 | * @return SettingSection[] Modified list of SettingSections. 45 | */ 46 | public function register( $sections ) { 47 | $sections[] = $this->section; 48 | 49 | return $sections; 50 | } 51 | 52 | /** 53 | * Get the value stored in the option. 54 | * If no values are found then the default values are returned. 55 | * 56 | * @return array Stored value. 57 | */ 58 | public function get_value() { 59 | $value = get_option( $this->section->option_name ); 60 | 61 | return wp_parse_args( $value, $this->section->default_value ); 62 | } 63 | 64 | /** 65 | * Customize the SettingSection. 66 | * 67 | * @return void 68 | */ 69 | abstract protected function initialize(); 70 | 71 | /** 72 | * Get the list of SettingFields. 73 | * 74 | * @return SettingField[] List of fields for the Setting. 75 | */ 76 | protected function get_fields() { 77 | return $this->build_fields(); 78 | } 79 | 80 | /** 81 | * Render the Settings section. 82 | * 83 | * By default it does nothing. 84 | */ 85 | public function render() { 86 | return; 87 | } 88 | 89 | /** 90 | * Sanitize the option values. 91 | * 92 | * @param mixed $values User entered values. 93 | * 94 | * @return mixed Sanitized values. 95 | */ 96 | public function sanitize( $values ) { 97 | if ( ! is_array( $values ) ) { 98 | return array(); 99 | } 100 | 101 | $values = wp_parse_args( $values, $this->section->default_value ); 102 | $sanitized_values = array(); 103 | 104 | foreach ( $this->section->field_labels as $field_id => $label ) { 105 | $callback = array( $this, 'sanitize_' . $field_id ); 106 | 107 | if ( is_callable( $callback ) ) { 108 | $sanitized_values[ $field_id ] = call_user_func( $callback, $values[ $field_id ] ); 109 | } else { 110 | $sanitized_values[ $field_id ] = $values[ $field_id ]; 111 | } 112 | } 113 | 114 | return $sanitized_values; 115 | } 116 | 117 | /** 118 | * Build SettingField objects from field id and labels. 119 | * 120 | * @since 2.1.0 121 | * 122 | * @return \EmailLog\Core\UI\Setting\SettingField[] Built SettingFields. 123 | */ 124 | protected function build_fields() { 125 | $fields = array(); 126 | 127 | foreach ( $this->section->field_labels as $field_id => $label ) { 128 | $field = new SettingField(); 129 | $field->id = $field_id; 130 | $field->title = $label; 131 | $field->args = array( 'id' => $field_id ); 132 | $field->callback = array( $this, 'render_' . $field_id . '_settings' ); 133 | 134 | $fields[] = $field; 135 | } 136 | 137 | return $fields; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /bin/install-wp-tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ $# -lt 3 ]; then 4 | echo "usage: $0 [db-host] [wp-version] [skip-database-creation]" 5 | exit 1 6 | fi 7 | 8 | DB_NAME=$1 9 | DB_USER=$2 10 | DB_PASS=$3 11 | DB_HOST=${4-localhost} 12 | WP_VERSION=${5-latest} 13 | SKIP_DB_CREATE=${6-false} 14 | 15 | WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib} 16 | WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/} 17 | 18 | download() { 19 | if [ `which curl` ]; then 20 | curl -s "$1" > "$2"; 21 | elif [ `which wget` ]; then 22 | wget -nv -O "$2" "$1" 23 | fi 24 | } 25 | 26 | if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then 27 | WP_TESTS_TAG="tags/$WP_VERSION" 28 | elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then 29 | WP_TESTS_TAG="trunk" 30 | else 31 | # http serves a single offer, whereas https serves multiple. we only want one 32 | download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json 33 | grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json 34 | LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') 35 | if [[ -z "$LATEST_VERSION" ]]; then 36 | echo "Latest WordPress version could not be found" 37 | exit 1 38 | fi 39 | WP_TESTS_TAG="tags/$LATEST_VERSION" 40 | fi 41 | 42 | set -ex 43 | 44 | install_wp() { 45 | 46 | if [ -d $WP_CORE_DIR ]; then 47 | return; 48 | fi 49 | 50 | mkdir -p $WP_CORE_DIR 51 | 52 | if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then 53 | mkdir -p /tmp/wordpress-nightly 54 | download https://wordpress.org/nightly-builds/wordpress-latest.zip /tmp/wordpress-nightly/wordpress-nightly.zip 55 | unzip -q /tmp/wordpress-nightly/wordpress-nightly.zip -d /tmp/wordpress-nightly/ 56 | mv /tmp/wordpress-nightly/wordpress/* $WP_CORE_DIR 57 | else 58 | if [ $WP_VERSION == 'latest' ]; then 59 | local ARCHIVE_NAME='latest' 60 | else 61 | local ARCHIVE_NAME="wordpress-$WP_VERSION" 62 | fi 63 | download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz 64 | tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR 65 | fi 66 | 67 | download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php 68 | } 69 | 70 | install_test_suite() { 71 | # portable in-place argument for both GNU sed and Mac OSX sed 72 | if [[ $(uname -s) == 'Darwin' ]]; then 73 | local ioption='-i .bak' 74 | else 75 | local ioption='-i' 76 | fi 77 | 78 | # set up testing suite if it doesn't yet exist 79 | if [ ! -d $WP_TESTS_DIR ]; then 80 | # set up testing suite 81 | mkdir -p $WP_TESTS_DIR 82 | svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes 83 | fi 84 | 85 | if [ ! -f wp-tests-config.php ]; then 86 | download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php 87 | # remove all forward slashes in the end 88 | WP_CORE_DIR=$(echo $WP_CORE_DIR | sed "s:/\+$::") 89 | sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php 90 | sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php 91 | sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php 92 | sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php 93 | sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php 94 | fi 95 | 96 | } 97 | 98 | install_db() { 99 | 100 | if [ ${SKIP_DB_CREATE} = "true" ]; then 101 | return 0 102 | fi 103 | 104 | # parse DB_HOST for port or socket references 105 | local PARTS=(${DB_HOST//\:/ }) 106 | local DB_HOSTNAME=${PARTS[0]}; 107 | local DB_SOCK_OR_PORT=${PARTS[1]}; 108 | local EXTRA="" 109 | 110 | if ! [ -z $DB_HOSTNAME ] ; then 111 | if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then 112 | EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" 113 | elif ! [ -z $DB_SOCK_OR_PORT ] ; then 114 | EXTRA=" --socket=$DB_SOCK_OR_PORT" 115 | elif ! [ -z $DB_HOSTNAME ] ; then 116 | EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" 117 | fi 118 | fi 119 | 120 | # create database 121 | mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA 122 | } 123 | 124 | install_wp 125 | install_test_suite 126 | install_db 127 | -------------------------------------------------------------------------------- /include/Addon/Upseller.php: -------------------------------------------------------------------------------- 1 | '; 33 | _e( 'Additional fields are available through More Fields add-on. ', 'email-log' ); 34 | 35 | if ( $this->is_bundle_license_valid() ) { 36 | echo ''; 37 | _e( 'Install it', 'email-log' ); 38 | echo ''; 39 | } else { 40 | echo ''; 41 | _e( 'Buy Now', 'email-log' ); 42 | echo ''; 43 | } 44 | 45 | echo ''; 46 | } 47 | 48 | /** 49 | * Renders Upsell message for Auto delete logs add-on in Log list page 50 | * if the number of logs is greater than 5000. 51 | * 52 | * @param int $total_logs Total number of logs. 53 | * 54 | */ 55 | public function upsell_auto_delete_logs_in_log_list_page( $total_logs ) { 56 | if ( $total_logs < 5000 ) { 57 | return; 58 | } 59 | 60 | if ( $this->is_addon_active( 'Auto Delete Logs' ) ) { 61 | return; 62 | } 63 | 64 | if ( ! class_exists( 'PAnD' ) || ! \PAnD::is_admin_notice_active( 'disable-DL-upsell-notice-5000' ) ) { 65 | return; 66 | } 67 | ?> 68 | 69 |
70 |

71 | Auto Delete Logs' 76 | ); 77 | ?> 78 |

79 |
80 | 81 | is_addon_active( 'Auto Delete Logs' ) ) { 89 | return; 90 | } 91 | 92 | ?> 93 |

94 | 95 | Auto Delete Logs' 99 | ); 100 | ?> 101 | 102 |

103 | get_licenser(); 115 | 116 | if ( $licenser->is_bundle_license_valid() ) { 117 | return true; 118 | } 119 | 120 | return $licenser->is_addon_active( $addon_name ); 121 | } 122 | 123 | /** 124 | * Has valid bundle license? 125 | * 126 | * @return bool True if bundle license is valid, false otherwise. 127 | */ 128 | protected function is_bundle_license_valid() { 129 | $licenser = email_log()->get_licenser(); 130 | 131 | if ( $licenser->is_bundle_license_valid() ) { 132 | return true; 133 | } 134 | 135 | return false; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /tests/wp-tests/Util/SanitizeEmailTest.php: -------------------------------------------------------------------------------- 1 | assertEquals( $expected, $actual ); 15 | } 16 | 17 | function test_email_is_valid() { 18 | $invalid_email = 'sudar@sudarmuthu'; 19 | 20 | $expected = ''; 21 | $actual = sanitize_email( $invalid_email ); 22 | 23 | $this->assertEquals( $expected, $actual ); 24 | } 25 | 26 | function test_email_with_name() { 27 | $email_with_name = 'Sudar Muthu'; 28 | 29 | $expected = 'Sudar Muthu '; 30 | $actual_1 = sanitize_email( $email_with_name ); 31 | $actual_2 = sanitize_email_with_name( $email_with_name ); 32 | 33 | $this->assertEquals( $expected, $actual_1 ); 34 | $this->assertEquals( $expected, $actual_2 ); 35 | } 36 | 37 | function test_email_with_name_and_space() { 38 | $email_with_name_and_space = ' Sudar Muthu '; 39 | 40 | $expected = 'Sudar Muthu '; 41 | $actual = sanitize_email( $email_with_name_and_space ); 42 | 43 | $this->assertEquals( $expected, $actual); 44 | } 45 | 46 | function test_multiple_simple_email_returns_first() { 47 | $multiple_emails = 'sudar@sudarmuthu.com, muthu@sudarmuthu.com'; 48 | 49 | $expected = 'sudar@sudarmuthu.com'; 50 | $actual = sanitize_email( $multiple_emails, false ); 51 | 52 | $this->assertEquals( $expected, $actual ); 53 | } 54 | 55 | function test_trimed_multiple_simple_email_returns_first() { 56 | $multiple_emails = ' sudar@sudarmuthu.com, muthu@sudarmuthu.com '; 57 | 58 | $expected = 'sudar@sudarmuthu.com'; 59 | $actual = sanitize_email( $multiple_emails, false ); 60 | 61 | $this->assertEquals( $expected, $actual ); 62 | } 63 | 64 | function test_multiple_simple_email_returns_all() { 65 | $multiple_emails = 'sudar@sudarmuthu.com, muthu@sudarmuthu.com'; 66 | 67 | $expected = 'sudar@sudarmuthu.com, muthu@sudarmuthu.com'; 68 | $actual = sanitize_email( $multiple_emails, true ); 69 | 70 | $this->assertEquals( $expected, $actual ); 71 | } 72 | 73 | function test_trimed_multiple_simple_email_returns_all() { 74 | $multiple_emails = ' sudar@sudarmuthu.com , muthu@sudarmuthu.com '; 75 | 76 | $expected = 'sudar@sudarmuthu.com, muthu@sudarmuthu.com'; 77 | $actual = sanitize_email( $multiple_emails, true ); 78 | 79 | $this->assertEquals( $expected, $actual ); 80 | } 81 | 82 | function test_multiple_simple_email() { 83 | $multiple_emails = 'sudar@sudarmuthu.com, muthu@sudarmuthu.com'; 84 | 85 | $expected = 'sudar@sudarmuthu.com, muthu@sudarmuthu.com'; 86 | $actual = sanitize_email( $multiple_emails ); 87 | 88 | $this->assertEquals( $expected, $actual ); 89 | } 90 | 91 | function test_trimed_multiple_simple_email() { 92 | $multiple_emails = ' sudar@sudarmuthu.com , muthu@sudarmuthu.com '; 93 | 94 | $expected = 'sudar@sudarmuthu.com, muthu@sudarmuthu.com'; 95 | $actual = sanitize_email( $multiple_emails ); 96 | 97 | $this->assertEquals( $expected, $actual ); 98 | } 99 | 100 | function test_multiple_email_with_name() { 101 | $multiple_emails = 'Sudar Muthu , Muthu'; 102 | 103 | $expected = 'Sudar Muthu , Muthu '; 104 | $actual = sanitize_email( $multiple_emails ); 105 | 106 | $this->assertEquals( $expected, $actual ); 107 | } 108 | 109 | function test_multiple_email_with_name_and_quotes() { 110 | $multiple_emails = '"Sudar Muthu" , "Muthu"'; 111 | 112 | $expected = '"Sudar Muthu" , "Muthu" '; 113 | $actual = sanitize_email( $multiple_emails ); 114 | 115 | $this->assertEquals( $expected, $actual ); 116 | } 117 | 118 | function test_multiple_email_with_name_returns_first() { 119 | $multiple_emails = 'Sudar Muthu , Muthu '; 120 | 121 | $expected = 'Sudar Muthu '; 122 | $actual = sanitize_email( $multiple_emails, false ); 123 | 124 | $this->assertEquals( $expected, $actual ); 125 | } 126 | } 127 | 128 | -------------------------------------------------------------------------------- /include/Core/UI/Component/EmailLogSystemInfo.php: -------------------------------------------------------------------------------- 1 | 40 | -- Email Log Configuration -- 41 | 42 | Email Log Version: 43 | Number of Logs: table_manager->get_logs_count() . "\n"; ?> 44 | Email Log DB Version: 45 | 46 | Additional allowed user roles: 47 | Remove All Data on Uninstallation: 48 | Disable DashBoard Widget: 49 | 50 | 51 | get_bundle_license(); 60 | 61 | if ( ! is_null( $bundle_license ) ) { 62 | $this->print_bundle_license_details( $bundle_license ); 63 | } else { 64 | $this->print_individual_addon_license(); 65 | } 66 | } 67 | 68 | /** 69 | * Get Bundle license. 70 | * 71 | * @return \EmailLog\Addon\License\BundleLicense|null Bundle license or null if no bundle license. 72 | */ 73 | protected function get_bundle_license() { 74 | $email_log = email_log(); 75 | 76 | $licenser = $email_log->get_licenser(); 77 | $bundle_license = $licenser->get_bundle_license(); 78 | 79 | $bundle_license_key = $bundle_license->get_license_key(); 80 | if ( ! empty( $bundle_license_key ) ) { 81 | return $bundle_license; 82 | } 83 | 84 | return null; 85 | } 86 | 87 | /** 88 | * Print bundle license details. 89 | * 90 | * @param \EmailLog\Addon\License\BundleLicense $bundle_license Bundle license. 91 | * 92 | * PHPCS is disabled for this function since alignment will mess up the system info output. 93 | * phpcs:disable 94 | */ 95 | protected function print_bundle_license_details( $bundle_license ) { 96 | ?> 97 | -- Email Log Bundle License -- 98 | 99 | License Key: get_license_key(), "\n"; ?> 100 | License Expiry Date: get_expiry_date(), "\n"; ?> 101 | is_valid() ) : ?> 102 | License Valid: 103 | 104 | License Valid: 105 | 106 | 107 | get_licenser(); 121 | $addons = $licenser->get_addon_list()->get_addons(); 122 | ?> 123 | -- Email Log Addon License -- 124 | 125 | name; 128 | 129 | $license_key = $addon->get_addon_license_key(); 130 | 131 | if ( ! empty( $license_key ) ) { 132 | $addon_license = $addon->get_license(); 133 | echo ' (', $license_key, ' - ', $addon_license->get_expiry_date(), ')'; 134 | } 135 | 136 | echo "\n"; 137 | } 138 | echo "\n"; 139 | } 140 | // phpcs:enable 141 | 142 | /** 143 | * Change the default config. 144 | * 145 | * @return array Modified config. 146 | */ 147 | protected function get_default_config() { 148 | $config = parent::get_default_config(); 149 | 150 | $config['show_posts'] = false; 151 | $config['show_taxonomies'] = false; 152 | $config['show_users'] = false; 153 | 154 | return $config; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /include/Core/EmailLog.php: -------------------------------------------------------------------------------- 1 | plugin_file = $file; 108 | $this->loader = $loader; 109 | $this->table_manager = $table_manager; 110 | 111 | $this->add_loadie( $table_manager ); 112 | 113 | $this->translations_path = dirname( plugin_basename( $this->plugin_file ) ) . '/languages/' ; 114 | } 115 | 116 | /** 117 | * Set Licenser. 118 | * 119 | * @param \EmailLog\Addon\License\Licenser $licenser Add-on Licenser. 120 | */ 121 | public function set_licenser( $licenser ) { 122 | if ( $this->add_loadie( $licenser ) ) { 123 | $this->licenser = $licenser; 124 | } 125 | } 126 | 127 | /** 128 | * Get Licenser. 129 | * 130 | * @return \EmailLog\Addon\License\Licenser|null 131 | */ 132 | public function get_licenser() { 133 | return $this->licenser; 134 | } 135 | 136 | /** 137 | * Add an Email Log Loadie. 138 | * The `load()` method of the Loadies will be called when Email Log is loaded. 139 | * 140 | * @param \EmailLog\Core\Loadie $loadie Loadie to be loaded. 141 | * 142 | * @return bool False if Email Log is already loaded or if $loadie is not of `Loadie` type. True otherwise. 143 | */ 144 | public function add_loadie( $loadie ) { 145 | if ( $this->loaded ) { 146 | return false; 147 | } 148 | 149 | if ( ! $loadie instanceof Loadie ) { 150 | return false; 151 | } 152 | 153 | $this->loadies[] = $loadie; 154 | 155 | return true; 156 | } 157 | 158 | /** 159 | * Load the plugin. 160 | */ 161 | public function load() { 162 | if ( $this->loaded ) { 163 | return; 164 | } 165 | 166 | load_plugin_textdomain( 'email-log', false, $this->translations_path ); 167 | 168 | $this->table_manager->load(); 169 | 170 | foreach ( $this->loadies as $loadie ) { 171 | $loadie->load(); 172 | } 173 | 174 | $this->loaded = true; 175 | 176 | /** 177 | * Email Log plugin loaded. 178 | * 179 | * @since 2.0 180 | */ 181 | do_action( 'el_loaded' ); 182 | } 183 | 184 | /** 185 | * Plugin API has been overridden. 186 | * 187 | * @since 2.4.5 188 | */ 189 | public function plugin_api_overridden() { 190 | $this->plugins_api_overridden = true; 191 | } 192 | 193 | /** 194 | * Has the plugin API have been overridden? 195 | * 196 | * @since 2.4.5 197 | * 198 | * @return bool True if overridden, False otherwise. 199 | */ 200 | public function is_plugin_api_overridden() { 201 | return $this->plugins_api_overridden; 202 | } 203 | 204 | /** 205 | * Return Email Log version. 206 | * 207 | * @return string Email Log Version. 208 | */ 209 | public function get_version() { 210 | return self::VERSION; 211 | } 212 | 213 | /** 214 | * Return the Email Log plugin directory path. 215 | * 216 | * @return string Plugin directory path. 217 | */ 218 | public function get_plugin_path() { 219 | return plugin_dir_path( $this->plugin_file ); 220 | } 221 | 222 | /** 223 | * Return the Email Log plugin file. 224 | * 225 | * @since 2.0.0 226 | * 227 | * @return string Plugin directory path. 228 | */ 229 | public function get_plugin_file() { 230 | return $this->plugin_file; 231 | } 232 | 233 | /** 234 | * Get Email Log Store URL. 235 | * 236 | * @since 2.0.0 237 | * 238 | * @return string Store URL 239 | */ 240 | public function get_store_url() { 241 | return self::STORE_URL; 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /tests/wp-tests/Util/EmailHeaderParserTest.php: -------------------------------------------------------------------------------- 1 | object = new EmailHeaderParser(); 13 | } 14 | 15 | public function tearDown() { 16 | parent::tearDown(); 17 | } 18 | 19 | /** 20 | * Test `join_headers` method. 21 | * 22 | * Include all the headers in the mock data. 23 | */ 24 | function test_join_headers_with_all_data() { 25 | $mock_data = array( 26 | 'from' => 'mariadanieldeepak@gmail.com', 27 | 'cc' => 'maria.danieldeepak@gmail.com', 28 | 'bcc' => 'mariadaniel.deepak@gmail.com', 29 | 'reply_to' => 'mariadanieldeepak@gmail.com', 30 | 'content_type' => 'text/html; charset=iso-8859-1', 31 | ); 32 | 33 | $line_break = "\r\n"; 34 | $expected = 'From: mariadanieldeepak@gmail.com' . $line_break; 35 | $expected .= 'CC: maria.danieldeepak@gmail.com' . $line_break; 36 | $expected .= 'BCC: mariadaniel.deepak@gmail.com' . $line_break; 37 | $expected .= 'Reply-to: mariadanieldeepak@gmail.com' . $line_break; 38 | $expected .= 'Content-type: text/html; charset=iso-8859-1' . $line_break; 39 | $actual = $this->object->join_headers( $mock_data ); 40 | 41 | $this->assertEquals( $expected, $actual ); 42 | } 43 | 44 | /** 45 | * Test `join_headers` method. 46 | * 47 | * Include few headers in the mock data. 48 | */ 49 | function test_join_headers_with_few_data() { 50 | $mock_data = array( 51 | 'from' => 'mariadanieldeepak@gmail.com', 52 | 'reply_to' => 'mariadanieldeepak@gmail.com' 53 | ); 54 | 55 | $line_break = "\r\n"; 56 | $expected = 'From: mariadanieldeepak@gmail.com' . $line_break; 57 | $expected .= 'Reply-to: mariadanieldeepak@gmail.com' . $line_break; 58 | $actual = $this->object->join_headers( $mock_data ); 59 | 60 | $this->assertEquals( $expected, $actual ); 61 | } 62 | 63 | /** 64 | * Test `join_headers` method. 65 | * 66 | * Test with mock data that has no header information. 67 | */ 68 | function test_join_headers_with_empty_data() { 69 | $mock_data = array( 70 | 'from' => '', 71 | 'cc' => '', 72 | 'bcc' => '', 73 | 'reply_to' => '', 74 | 'content_type' => '', 75 | ); 76 | 77 | $expected = ''; 78 | $actual = $this->object->join_headers( $mock_data ); 79 | 80 | $this->assertEquals( $expected, $actual ); 81 | } 82 | 83 | /** 84 | * Test `parse_headers` method. 85 | * 86 | * Test with all headers. 87 | */ 88 | function test_parse_with_all_data() { 89 | $line_break = "\r\n"; 90 | $mock_headers = 'From: mariadanieldeepak@gmail.com' . $line_break; 91 | $mock_headers .= 'CC: maria.danieldeepak@gmail.com' . $line_break; 92 | $mock_headers .= 'BCC: mariadaniel.deepak@gmail.com' . $line_break; 93 | $mock_headers .= 'Reply-to: mariadanieldeepak@gmail.com' . $line_break; 94 | $mock_headers .= 'Content-type: text/html; charset=iso-8859-1' . $line_break; 95 | 96 | $expected = array( 97 | 'from' => 'mariadanieldeepak@gmail.com', 98 | 'cc' => 'maria.danieldeepak@gmail.com', 99 | 'bcc' => 'mariadaniel.deepak@gmail.com', 100 | 'reply_to' => 'mariadanieldeepak@gmail.com', 101 | 'content_type' => 'text/html; charset=iso-8859-1', 102 | ); 103 | $actual = $this->object->parse_headers( $mock_headers ); 104 | 105 | $this->assertEquals( $expected, $actual ); 106 | } 107 | 108 | /** 109 | * Test `parse_headers` method. 110 | * 111 | * Test with quotes in headers. 112 | */ 113 | function test_parse_with_quotes() { 114 | $line_break = "\r\n"; 115 | $mock_headers = 'From: "Maria Daniel" ' . $line_break; 116 | $mock_headers .= 'CC: maria.danieldeepak@gmail.com' . $line_break; 117 | $mock_headers .= 'BCC: mariadaniel.deepak@gmail.com' . $line_break; 118 | $mock_headers .= 'Reply-to: "Maria Daniel" ' . $line_break; 119 | $mock_headers .= 'Content-type: text/html; charset=iso-8859-1' . $line_break; 120 | 121 | $expected = array( 122 | 'from' => '"Maria Daniel" ', 123 | 'cc' => 'maria.danieldeepak@gmail.com', 124 | 'bcc' => 'mariadaniel.deepak@gmail.com', 125 | 'reply_to' => '"Maria Daniel" ', 126 | 'content_type' => 'text/html; charset=iso-8859-1', 127 | ); 128 | $actual = $this->object->parse_headers( $mock_headers ); 129 | 130 | $this->assertEquals( $expected, $actual ); 131 | } 132 | /** 133 | * Test `parse_headers` method. 134 | * 135 | * Test with few headers information. 136 | */ 137 | function test_parse_with_few_data() { 138 | $line_break = "\r\n"; 139 | $mock_headers = 'CC: maria.danieldeepak@gmail.com' . $line_break; 140 | $mock_headers .= 'BCC: mariadaniel.deepak@gmail.com' . $line_break; 141 | $mock_headers .= 'Content-type: text/html; charset=iso-8859-1' . $line_break; 142 | 143 | $expected = array( 144 | 'cc' => 'maria.danieldeepak@gmail.com', 145 | 'bcc' => 'mariadaniel.deepak@gmail.com', 146 | 'content_type' => 'text/html; charset=iso-8859-1', 147 | ); 148 | $actual = $this->object->parse_headers( $mock_headers ); 149 | 150 | $this->assertEquals( $expected, $actual ); 151 | } 152 | 153 | /** 154 | * Test `parse_headers` method. 155 | * 156 | * Test with no header information. 157 | */ 158 | function test_parse_with_no_data() { 159 | $mock_headers = ''; 160 | $expected = array(); 161 | $actual = $this->object->parse_headers( $mock_headers ); 162 | 163 | $this->assertEquals( $expected, $actual ); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /include/Addon/AddonList.php: -------------------------------------------------------------------------------- 1 | get_store_url(); 39 | } 40 | $this->store_url = $store_url; 41 | 42 | if ( null === $addons ) { 43 | $addons = $this->get_addons(); 44 | } 45 | 46 | $this->addons = $addons; 47 | } 48 | 49 | /** 50 | * Get an add-on by name. 51 | * 52 | * @param string $name Add-on name. 53 | * 54 | * @return \EmailLog\Addon\Addon|false Add-on if found, False otherwise. 55 | */ 56 | public function get_addon_by_name( $name ) { 57 | if ( array_key_exists( $name, $this->addons ) ) { 58 | return $this->addons[ $name ]; 59 | } 60 | 61 | return false; 62 | } 63 | 64 | /** 65 | * Is an add-on active? 66 | * 67 | * @since 2.4.0 68 | * 69 | * @param string $name Add-on name. 70 | * 71 | * @return bool True if add-on is present and is active, false otherwise. 72 | */ 73 | public function is_addon_active( $name ) { 74 | $addon = $this->get_addon_by_name( $name ); 75 | 76 | if ( ! $addon instanceof Addon ) { 77 | return false; 78 | } 79 | 80 | return $addon->is_active(); 81 | } 82 | 83 | /** 84 | * Is an add-on installed? 85 | * 86 | * @since 2.4.0 87 | * 88 | * @param string $name Add-on name. 89 | * 90 | * @return bool True if add-on is present and is installed, false otherwise. 91 | */ 92 | public function is_addon_installed( $name ) { 93 | $addon = $this->get_addon_by_name( $name ); 94 | 95 | if ( ! $addon instanceof Addon ) { 96 | return false; 97 | } 98 | 99 | return $addon->is_installed(); 100 | } 101 | 102 | /** 103 | * Get all add-ons that are not active (either not installed or not activated). 104 | * 105 | * @return \EmailLog\Addon\Addon[] List of inactive add-ons. 106 | */ 107 | public function get_inactive_addons() { 108 | $inactive_addons = array(); 109 | 110 | foreach ( $this->addons as $addon ) { 111 | if ( ! $addon->is_active() ) { 112 | $inactive_addons[] = $addon; 113 | } 114 | } 115 | 116 | return $inactive_addons; 117 | } 118 | 119 | /** 120 | * Setup page to render the list of add-ons. 121 | */ 122 | public function render() { 123 | ?> 124 | 125 |
126 | render_addons(); ?> 127 |
128 | get_api_url() ); 141 | 142 | if ( is_wp_error( $response ) || ! is_array( $response ) ) { 143 | return []; 144 | } 145 | 146 | $json = json_decode( wp_remote_retrieve_body( $response ), true ); 147 | 148 | if ( ! is_array( $json ) ) { 149 | return array(); 150 | } 151 | 152 | set_transient( self::CACHE_KEY, $json, self::CACHE_EXPIRY_IN_HRS * HOUR_IN_SECONDS ); 153 | } 154 | 155 | return $this->parse_response( $json ); 156 | } 157 | 158 | /** 159 | * Parse the response and get the list of add-on. 160 | * 161 | * @param array $data JSON Data array. 162 | * 163 | * @return array List of Add-ons. 164 | */ 165 | protected function parse_response( $data ) { 166 | if ( ! array_key_exists( 'products', $data ) ) { 167 | return array(); 168 | } 169 | 170 | return $this->build_addon_list( $data['products'] ); 171 | } 172 | 173 | /** 174 | * Build a list of Addon objects from products data array. 175 | * 176 | * @param array $products Products data array. 177 | * 178 | * @return Addon[] List of Addons. 179 | */ 180 | protected function build_addon_list( $products ) { 181 | $addons = array(); 182 | 183 | foreach ( $products as $product ) { 184 | $addon = new Addon( $product ); 185 | $addons[ $addon->name ] = $addon; 186 | } 187 | 188 | return $addons; 189 | } 190 | 191 | /** 192 | * Render the add-on list or display an error if the list can't be retrieved. 193 | */ 194 | protected function render_addons() { 195 | if ( empty( $this->addons ) ) { 196 | $this->render_empty_list(); 197 | } 198 | 199 | foreach ( $this->addons as $addon ) { 200 | $addon->render(); 201 | } 202 | } 203 | 204 | /** 205 | * Display a notice if the list of add-on can't be retrieved. 206 | */ 207 | protected function render_empty_list() { 208 | ?> 209 | 210 | add-on page to view the add-ons.', 'email-log' ), // @codingStandardsIgnoreLine 213 | 'https://wpemaillog.com/store/?utm_campaign=Upsell&utm_medium=wpadmin&utm_source=addon-grid-failed' 214 | ); 215 | ?> 216 | 217 | store_url . '/json/products.json'; 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /include/Core/UI/Page/LogListPage.php: -------------------------------------------------------------------------------- 1 | page = add_submenu_page( 67 | self::PAGE_SLUG, 68 | __( 'View Logs', 'email-log'), 69 | __( 'View Logs', 'email-log'), 70 | self::CAPABILITY, 71 | self::PAGE_SLUG, 72 | array( $this, 'render_page' ) 73 | ); 74 | 75 | add_action( "load-{$this->page}", array( $this, 'load_page' ) ); 76 | 77 | /** 78 | * Fires before loading log list page. 79 | * 80 | * @since 2.0 81 | * 82 | * @param string $page Page slug. 83 | */ 84 | do_action( 'el_load_log_list_page', $this->page ); 85 | } 86 | 87 | /** 88 | * Render page. 89 | */ 90 | public function render_page() { 91 | if ( ! current_user_can( self::CAPABILITY ) ) { 92 | return; 93 | } 94 | 95 | add_thickbox(); 96 | 97 | $this->log_list_table->prepare_items(); 98 | ?> 99 |
100 |

101 | 102 | 103 |
104 | 105 | log_list_table->search_box( __( 'Search Logs', 'email-log' ), 'search_id' ); ?> 106 | 107 | log_list_table->display(); 111 | ?> 112 |
113 |
114 | render_page_footer(); 116 | } 117 | 118 | /** 119 | * Load page. 120 | */ 121 | public function load_page() { 122 | $this->render_help_tab(); 123 | 124 | // Add screen options 125 | $this->get_screen()->add_option( 126 | 'per_page', 127 | array( 128 | 'label' => __( 'Entries per page', 'email-log' ), 129 | 'default' => 20, 130 | 'option' => 'per_page', 131 | ) 132 | ); 133 | 134 | $this->log_list_table = new LogListTable( $this ); 135 | } 136 | 137 | /** 138 | * Gets the per page option. 139 | * 140 | * @return int Number of logs a user wanted to be displayed in a page. 141 | */ 142 | public function get_per_page() { 143 | $screen = get_current_screen(); 144 | $option = $screen->get_option( 'per_page', 'option' ); 145 | 146 | $per_page = get_user_meta( get_current_user_id(), $option, true ); 147 | 148 | if ( empty( $per_page ) || $per_page < 1 ) { 149 | $per_page = $screen->get_option( 'per_page', 'default' ); 150 | } 151 | 152 | return $per_page; 153 | } 154 | 155 | /** 156 | * Get nonce args. 157 | * 158 | * @return array Nonce args. 159 | */ 160 | public function get_nonce_args() { 161 | return array( 162 | self::LOG_LIST_ACTION_NONCE_FIELD => wp_create_nonce( self::LOG_LIST_ACTION_NONCE ), 163 | ); 164 | } 165 | 166 | /** 167 | * Get TableManager instance. 168 | * 169 | * @return TableManager TableManager instance. 170 | */ 171 | public function get_table_manager() { 172 | $email_log = email_log(); 173 | 174 | return $email_log->table_manager; 175 | } 176 | 177 | /** 178 | * Saves Screen options. 179 | * 180 | * @since Genesis 181 | * 182 | * @param bool|int $status Screen option value. Default false to skip. 183 | * @param string $option The option name. 184 | * @param int $value The number of rows to use. 185 | * 186 | * @return bool|int 187 | */ 188 | public function save_screen_options( $status, $option, $value ) { 189 | if ( 'per_page' == $option ) { 190 | return $value; 191 | } else { 192 | return $status; 193 | } 194 | } 195 | 196 | /** 197 | * Loads assets on the Log List page. 198 | * 199 | * @since 2.0.0 200 | * 201 | * @param string $hook The current admin page. 202 | */ 203 | public function load_view_logs_assets( $hook ) { 204 | // Don't load assets if not View Logs page. 205 | if ( 'toplevel_page_email-log' !== $hook ) { 206 | return; 207 | } 208 | 209 | $email_log = email_log(); 210 | $plugin_dir_url = plugin_dir_url( $email_log->get_plugin_file() ); 211 | 212 | wp_register_style( 'jquery-ui-css', $plugin_dir_url . 'assets/vendor/jquery-ui/themes/base/jquery-ui.min.css', array(), '1.12.1' ); 213 | wp_enqueue_style( 'el-view-logs-css', $plugin_dir_url . 'assets/css/admin/view-logs.css', array( 'jquery-ui-css' ), $email_log->get_version() ); 214 | 215 | wp_register_script( 'insertionQ', $plugin_dir_url . 'assets/vendor/insertion-query/insQ.min.js', array( 'jquery' ), '1.0.4', true ); 216 | 217 | wp_enqueue_script( 'el-view-logs', $plugin_dir_url . 'assets/js/admin/view-logs.js', array( 'insertionQ', 'jquery-ui-core', 'jquery-ui-datepicker', 'jquery-ui-tooltip', 'jquery-ui-tabs' ), $email_log->get_version(), true ); 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /include/Core/EmailLogger.php: -------------------------------------------------------------------------------- 1 | '', 59 | 'subject' => '', 60 | 'message' => '', 61 | 'headers' => '', 62 | 'attachments' => array(), 63 | ) 64 | ); 65 | 66 | $log = array( 67 | 'to_email' => \EmailLog\Util\stringify( $mail_info['to'] ), 68 | 'subject' => $mail_info['subject'], 69 | 'message' => $mail_info['message'], 70 | 'headers' => \EmailLog\Util\stringify( $mail_info['headers'], "\n" ), 71 | 'attachment_name' => \EmailLog\Util\stringify( $mail_info['attachments'] ), 72 | 'sent_date' => current_time( 'mysql' ), 73 | 'ip_address' => $_SERVER['REMOTE_ADDR'], 74 | 'result' => 1, 75 | ); 76 | 77 | if ( empty( $log['attachment_name'] ) ) { 78 | $log['attachments'] = 'false'; 79 | } else { 80 | $log['attachments'] = 'true'; 81 | } 82 | 83 | /** 84 | * Filters the mail info right before inserting on the table. 85 | * 86 | * Masked fields would use this filter to avoid modifying the original data sent to 87 | * `wp_mail() function` 88 | * 89 | * @param array $log Email Log that is about to be inserted into db. 90 | * @param array $original_mail_info Original mail info that was passed to `wp_mail` filter. 91 | * 92 | * @since 2.3.2 93 | */ 94 | $log = apply_filters( 'el_email_log_before_insert', $log, $original_mail_info ); 95 | 96 | $email_log = email_log(); 97 | $email_log->table_manager->insert_log( $log ); 98 | 99 | /** 100 | * Fires the `el_email_log_inserted` action right after the log is inserted in to DB. 101 | * 102 | * @since 2.3.0 103 | * 104 | * @param array $log { 105 | * @type string $to 106 | * @type string $subject 107 | * @type string $message 108 | * @type string $headers 109 | * @type string $attachments 110 | * @type string $attachment_name 111 | * @type string $sent_date 112 | * @type string $ip_address 113 | * @type bool $result 114 | * } 115 | */ 116 | do_action( 'el_email_log_inserted', $log ); 117 | 118 | return $original_mail_info; 119 | } 120 | 121 | /** 122 | * Updates the failed email in the DB. 123 | * 124 | * @param \WP_Error $wp_error The error instance. 125 | * 126 | * @since 2.4.0 Use is_wp_error() to validate the type of $wp_error. 127 | * @since 2.3.0 128 | * 129 | * @see is_wp_error() 130 | * @see email_log() 131 | */ 132 | public function on_email_failed( $wp_error ) { 133 | if ( ! is_wp_error( $wp_error ) ) { 134 | return; 135 | } 136 | 137 | // @see wp-includes/pluggable.php#500 138 | $mail_error_data = $wp_error->get_error_data( 'wp_mail_failed' ); 139 | $mail_error_message = $wp_error->get_error_message( 'wp_mail_failed' ); 140 | 141 | $this->mark_email_log_as_failed( $mail_error_data, $mail_error_message ); 142 | } 143 | 144 | /** 145 | * Prepare BuddyPress emails to log into database. 146 | * 147 | * @since 2.3.2 148 | * 149 | * @param bool $status Mail sent status. 150 | * @param \BP_Email $bp_mail Information about email. 151 | */ 152 | public function log_buddy_press_email( $status, $bp_mail ) { 153 | if ( ! class_exists( '\\BP_Email' ) ) { 154 | return; 155 | } 156 | 157 | if ( $bp_mail instanceof \BP_Email ) { 158 | return; 159 | } 160 | 161 | $log = array( 162 | 'to' => array_shift( $bp_mail->get_to() )->get_address(), 163 | 'subject' => $bp_mail->get_subject( 'replace-tokens' ), 164 | 'message' => $bp_mail->get_content( 'replace-tokens' ), 165 | 'headers' => $bp_mail->get_headers( 'replace-tokens ' ), 166 | ); 167 | 168 | $this->log_email( $log ); 169 | 170 | if ( ! $status ) { 171 | $this->mark_email_log_as_failed( $log ); 172 | } 173 | } 174 | 175 | /** 176 | * Mark email log as failed. 177 | * 178 | * @param array $log Email Log. 179 | * @param string $error_message Error message. 180 | * 181 | * @since 2.3.2 182 | * @since 2.4.0 Store the error message. 183 | */ 184 | protected function mark_email_log_as_failed( $log, $error_message = '' ) { 185 | if ( ! is_array( $log ) ) { 186 | return; 187 | } 188 | 189 | if ( ! isset( $log['to'], $log['subject'] ) ) { 190 | return; 191 | } 192 | 193 | $email_log = email_log(); 194 | 195 | $log_item_id = $email_log->table_manager->fetch_log_id_by_data( $log ); 196 | 197 | if ( empty( $log_item_id ) ) { 198 | return; 199 | } 200 | 201 | $email_log->table_manager->mark_log_as_failed( $log_item_id, $error_message ); 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /languages/email-log-de_DE.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Email Log WordPress Plugin 0.2\n" 4 | "Report-Msgid-Bugs-To: http://wordpress.org/tag/email-log\n" 5 | "POT-Creation-Date: 2009-10-08 17:51+0000\n" 6 | "PO-Revision-Date: \n" 7 | "Last-Translator: \n" 8 | "Language-Team: Frank Weichbrodt\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "X-Poedit-Language: German\n" 13 | "X-Poedit-Country: GERMANY\n" 14 | 15 | #. #-#-#-#-# email-log.pot (Email Log 0.1) #-#-#-#-# 16 | #. Plugin Name of an extension 17 | #: email-log.php:58 18 | msgid "Email Log" 19 | msgstr "E-Mail Log" 20 | 21 | #: email-log.php:69 22 | msgid "Settings" 23 | msgstr "Einstellungen" 24 | 25 | #: email-log.php:79 26 | msgid "plugin" 27 | msgstr "Plugin" 28 | 29 | #: email-log.php:79 30 | msgid "Version" 31 | msgstr "Version" 32 | 33 | #: email-log.php:79 34 | msgid "by" 35 | msgstr "von" 36 | 37 | #: email-log.php:109 38 | #: email-log.php:463 39 | #: email-log.php:487 40 | msgid "Delete Logs" 41 | msgstr "Logs löschen" 42 | 43 | #: email-log.php:118 44 | #, php-format 45 | msgid "All Email Logs For email id %s Have Been Deleted." 46 | msgstr "Alle E-Mail Logs mit ID %s wurden gelöscht." 47 | 48 | #: email-log.php:120 49 | #, php-format 50 | msgid "An Error Has Occured while deleting All Email Logs For email id %s." 51 | msgstr "Beim Löschen der E-Mail Logs mit der ID %s ist ein Fehler aufgetreten." 52 | 53 | #: email-log.php:128 54 | #, php-format 55 | msgid "All Email Logs With Subject %s Have Been Deleted." 56 | msgstr "Alle E-Mail Logs mit dem Betreff %s wurden gelöscht." 57 | 58 | #: email-log.php:130 59 | #, php-format 60 | msgid "An Error Has Occured While Deleting All Email Logs With Subject %s." 61 | msgstr "Beim Löschen der E-Mail Logs mit dem Betreff %s ist ein Fehler aufgetreten." 62 | 63 | #: email-log.php:138 64 | msgid "All Email log Has Been Deleted." 65 | msgstr "Alle E-Mail Logs wurden gelöscht." 66 | 67 | #: email-log.php:140 68 | msgid "An Error Has Occured While Deleting All Email Logs" 69 | msgstr "Beim Löschen aller E-Mail Logs ist ein Fehler aufgetreten." 70 | 71 | #: email-log.php:174 72 | #: email-log.php:311 73 | #: email-log.php:346 74 | #: email-log.php:430 75 | msgid "ID" 76 | msgstr "ID" 77 | 78 | #: email-log.php:178 79 | #: email-log.php:431 80 | #: email-log.php:480 81 | msgid "To Email" 82 | msgstr "Empfänger" 83 | 84 | #: email-log.php:182 85 | #: email-log.php:314 86 | #: email-log.php:349 87 | #: email-log.php:432 88 | #: email-log.php:482 89 | msgid "Subject" 90 | msgstr "Betreff" 91 | 92 | #: email-log.php:187 93 | #: email-log.php:433 94 | msgid "Date" 95 | msgstr "Datum" 96 | 97 | #: email-log.php:194 98 | #: email-log.php:437 99 | msgid "Ascending" 100 | msgstr "aufsteigend" 101 | 102 | #: email-log.php:199 103 | #: email-log.php:438 104 | msgid "Descending" 105 | msgstr "absteigend" 106 | 107 | #: email-log.php:248 108 | msgid "Email Log Settings" 109 | msgstr "E-Mail Log - Einstellungen" 110 | 111 | #: email-log.php:249 112 | #, php-format 113 | msgid "Displaying %s to %s of %s Email log entries." 114 | msgstr "Anzeige: %s bis %s von %s Einträgen." 115 | 116 | #: email-log.php:250 117 | #, php-format 118 | msgid "Sorted by %s in %s order." 119 | msgstr "Sortiert nach %s in %ser Reihenfolge." 120 | 121 | #: email-log.php:261 122 | #: email-log.php:361 123 | msgid "Previous Page" 124 | msgstr "Vorherige Seite" 125 | 126 | #: email-log.php:268 127 | #: email-log.php:368 128 | #, php-format 129 | msgid "Pages (%s): " 130 | msgstr "Seiten (%s): " 131 | 132 | #: email-log.php:271 133 | #: email-log.php:371 134 | msgid "Go to First Page" 135 | msgstr "Gehe zur ersten Seite" 136 | 137 | #: email-log.php:271 138 | #: email-log.php:371 139 | msgid "First" 140 | msgstr "Erste" 141 | 142 | #: email-log.php:274 143 | #: email-log.php:286 144 | #: email-log.php:374 145 | #: email-log.php:386 146 | msgid "Go to Page" 147 | msgstr "Gehe zu Seite" 148 | 149 | #: email-log.php:281 150 | #: email-log.php:381 151 | msgid "Page" 152 | msgstr "Seite" 153 | 154 | #: email-log.php:289 155 | #: email-log.php:389 156 | msgid "Go to Last Page" 157 | msgstr "Gehe zur letzten Seite" 158 | 159 | #: email-log.php:289 160 | #: email-log.php:389 161 | msgid "Last" 162 | msgstr "Letzte" 163 | 164 | #: email-log.php:296 165 | #: email-log.php:396 166 | msgid "Next Page" 167 | msgstr "Nächste Seite" 168 | 169 | #: email-log.php:312 170 | #: email-log.php:347 171 | msgid "Date / Time" 172 | msgstr "Datum / Zeit" 173 | 174 | #: email-log.php:313 175 | #: email-log.php:348 176 | msgid "To" 177 | msgstr "An" 178 | 179 | #: email-log.php:328 180 | #, php-format 181 | msgid "%s @ %s" 182 | msgstr "%s @ %s" 183 | 184 | #: email-log.php:340 185 | msgid "No email Logs Found" 186 | msgstr "Keine E-Mail Logs gefunden." 187 | 188 | #: email-log.php:416 189 | msgid "Filter Options:" 190 | msgstr "Filter Optionen:" 191 | 192 | #: email-log.php:418 193 | msgid "ID:" 194 | msgstr "ID:" 195 | 196 | #: email-log.php:420 197 | msgid "To Email:" 198 | msgstr "Empfänger:" 199 | 200 | #: email-log.php:422 201 | msgid "Subject:" 202 | msgstr "Betreff:" 203 | 204 | #: email-log.php:427 205 | msgid "Sort Options:" 206 | msgstr "Sortierung:" 207 | 208 | #: email-log.php:445 209 | #: email-log.php:447 210 | msgid "Per Page" 211 | msgstr "je Seite" 212 | 213 | #: email-log.php:455 214 | msgid "Go" 215 | msgstr "Los" 216 | 217 | #: email-log.php:469 218 | msgid "Delete Type : " 219 | msgstr "Löschen:" 220 | 221 | #: email-log.php:472 222 | msgid "Based on" 223 | msgstr "wenn Bedingung zutrifft" 224 | 225 | #: email-log.php:473 226 | msgid "All Logs" 227 | msgstr "alle Einträge" 228 | 229 | #: email-log.php:478 230 | msgid "Condition:" 231 | msgstr "Bedingung:" 232 | 233 | #: email-log.php:481 234 | msgid "or" 235 | msgstr "oder" 236 | 237 | #: email-log.php:487 238 | msgid "" 239 | "You Are About To Delete Email Logs.\\n" 240 | "This Action Is Not Reversible.\\n" 241 | "\\n" 242 | " Choose \\'Cancel\\' to stop, \\'OK\\' to delete." 243 | msgstr "" 244 | "Du willst die E-Mail Logs löschen.\\n" 245 | "Diese Aktion lässt sich nicht rückgängig machen." 246 | 247 | #. Plugin URI of an extension 248 | msgid "http://sudarmuthu.com/wordpress/email-log" 249 | msgstr "http://sudarmuthu.com/wordpress/email-log" 250 | 251 | #. Description of an extension 252 | msgid "Logs every email sent through WordPress. Compatiable with WPMU too." 253 | msgstr "Logt jede von WordPress gesendete E-Mail. Kompatibel mit WPMU." 254 | 255 | #. Author of an extension 256 | msgid "Sudar" 257 | msgstr "Sudar" 258 | 259 | #. Author URI of an extension 260 | msgid "http://sudarmuthu.com/" 261 | msgstr "http://sudarmuthu.com/" 262 | 263 | -------------------------------------------------------------------------------- /include/EmailLogAutoloader.php: -------------------------------------------------------------------------------- 1 | register(); 35 | * 36 | * // register the base directories for the namespace prefix 37 | * $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src'); 38 | * $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/tests'); 39 | * 40 | * The following line would cause the autoloader to attempt to load the 41 | * \Foo\Bar\Qux\Quux class from /path/to/packages/foo-bar/src/Qux/Quux.php: 42 | * 43 | * files as $file ) { 79 | $this->require_file( $file ); 80 | } 81 | } 82 | 83 | /** 84 | * Adds a base directory for a namespace prefix. 85 | * 86 | * @param string $prefix The namespace prefix. 87 | * @param string $base_dir A base directory for class files in the 88 | * namespace. 89 | * @param bool $prepend If true, prepend the base directory to the stack 90 | * instead of appending it; this causes it to be searched first rather 91 | * than last. 92 | * 93 | * @return void 94 | */ 95 | public function add_namespace( $prefix, $base_dir, $prepend = false ) { 96 | // normalize namespace prefix 97 | $prefix = trim( $prefix, '\\' ) . '\\'; 98 | 99 | // normalize the base directory with a trailing separator 100 | $base_dir = rtrim( $base_dir, DIRECTORY_SEPARATOR ) . '/'; 101 | 102 | // initialize the namespace prefix array 103 | if ( false === isset( $this->prefixes[ $prefix ] ) ) { 104 | $this->prefixes[ $prefix ] = array(); 105 | } 106 | 107 | // retain the base directory for the namespace prefix 108 | if ( $prepend ) { 109 | array_unshift( $this->prefixes[ $prefix ], $base_dir ); 110 | } else { 111 | array_push( $this->prefixes[ $prefix ], $base_dir ); 112 | } 113 | } 114 | 115 | /** 116 | * Add a file to be autoloaded. 117 | * 118 | * @param string $filename File to be autoloaded. 119 | */ 120 | public function add_file( $filename ) { 121 | if ( ! in_array( $filename, $this->files, true ) ) { 122 | $this->files[] = $filename; 123 | } 124 | } 125 | 126 | /** 127 | * Loads the class file for a given class name. 128 | * 129 | * @param string $class The fully-qualified class name. 130 | * 131 | * @return false|string The mapped file name on success, or boolean false on 132 | * failure. 133 | */ 134 | public function load_class( $class ) { 135 | // the current namespace prefix 136 | $prefix = $class; 137 | 138 | // work backwards through the namespace names of the fully-qualified 139 | // class name to find a mapped file name 140 | while ( false !== $pos = strrpos( $prefix, '\\' ) ) { 141 | 142 | // retain the trailing namespace separator in the prefix 143 | $prefix = substr( $class, 0, $pos + 1 ); 144 | 145 | // the rest is the relative class name 146 | $relative_class = substr( $class, $pos + 1 ); 147 | 148 | // try to load a mapped file for the prefix and relative class 149 | $mapped_file = $this->load_mapped_file( $prefix, $relative_class ); 150 | if ( $mapped_file !== false ) { 151 | return $mapped_file; 152 | } 153 | 154 | // remove the trailing namespace separator for the next iteration 155 | // of strrpos() 156 | $prefix = rtrim( $prefix, '\\' ); 157 | } 158 | 159 | // never found a mapped file 160 | return false; 161 | } 162 | 163 | /** 164 | * Load the mapped file for a namespace prefix and relative class. 165 | * 166 | * @param string $prefix The namespace prefix. 167 | * @param string $relative_class The relative class name. 168 | * 169 | * @return false|string Boolean false if no mapped file can be loaded, or the 170 | * name of the mapped file that was loaded. 171 | */ 172 | protected function load_mapped_file( $prefix, $relative_class ) { 173 | // are there any base directories for this namespace prefix? 174 | if ( false === isset( $this->prefixes[ $prefix ] ) ) { 175 | return false; 176 | } 177 | 178 | // look through base directories for this namespace prefix 179 | foreach ( $this->prefixes[ $prefix ] as $base_dir ) { 180 | 181 | // replace the namespace prefix with the base directory, 182 | // replace namespace separators with directory separators 183 | // in the relative class name, append with .php 184 | $file = $base_dir 185 | . str_replace( '\\', '/', $relative_class ) 186 | . '.php'; 187 | 188 | // if the mapped file exists, require it 189 | if ( $this->require_file( $file ) ) { 190 | // yes, we're done 191 | return $file; 192 | } 193 | } 194 | 195 | // never found it 196 | return false; 197 | } 198 | 199 | /** 200 | * If a file exists, require it from the file system. 201 | * 202 | * @param string $file The file to require. 203 | * 204 | * @return bool True if the file exists, false if not. 205 | */ 206 | protected function require_file( $file ) { 207 | if ( file_exists( $file ) ) { 208 | require_once $file; 209 | 210 | return true; 211 | } 212 | 213 | return false; 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /languages/email-log-lt_LT.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Email Log WordPress Plugin 0.2\n" 4 | "Report-Msgid-Bugs-To: http://wordpress.org/tag/email-log\n" 5 | "POT-Creation-Date: 2009-10-08 17:51+0000\n" 6 | "PO-Revision-Date: \n" 7 | "Last-Translator: \n" 8 | "Language-Team: Frank Weichbrodt\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "X-Poedit-Language: German\n" 13 | "X-Poedit-Country: GERMANY\n" 14 | 15 | #. #-#-#-#-# email-log.pot (Email Log 0.1) #-#-#-#-# 16 | #. Plugin Name of an extension 17 | #: email-log.php:58 18 | msgid "Email Log" 19 | msgstr "Email Log" 20 | 21 | #: email-log.php:69 22 | msgid "Settings" 23 | msgstr "Nuostatos" 24 | 25 | #: email-log.php:79 26 | msgid "plugin" 27 | msgstr "papildinio" 28 | 29 | #: email-log.php:79 30 | msgid "Version" 31 | msgstr "Versija" 32 | 33 | #: email-log.php:79 34 | msgid "by" 35 | msgstr "pagal" 36 | 37 | #: email-log.php:109 38 | #: email-log.php:463 39 | #: email-log.php:487 40 | msgid "Delete Logs" 41 | msgstr "Ištrinti Žurnalo įrašus" 42 | 43 | #: email-log.php:118 44 | #, php-format 45 | msgid "All Email Logs For email id %s Have Been Deleted." 46 | msgstr "Visi Elektroninio pašto Žurnalo įrašai, Priskirti elektroninio pašto adresui su identifikatoriumi %s Buvo Ištrinti." 47 | 48 | #: email-log.php:120 49 | #, php-format 50 | msgid "An Error Has Occured while deleting All Email Logs For email id %s." 51 | msgstr "Įvyko Klaida, ištrinant Visus Elektroninio pašto Žurnalo įrašus, priskirtus elektroniniam paštui su identfiikatoriumi %s." 52 | 53 | #: email-log.php:128 54 | #, php-format 55 | msgid "All Email Logs With Subject %s Have Been Deleted." 56 | msgstr "Visi Elektroninio pašto Žurnalo įrašai, su antrašte %s Buvo Ištrinti." 57 | 58 | #: email-log.php:130 59 | #, php-format 60 | msgid "An Error Has Occured While Deleting All Email Logs With Subject %s." 61 | msgstr "Įvyko Klaida, ištrinant Visus Elekektroninio pašto Žurnalo įrašus su antrašte %s." 62 | 63 | #: email-log.php:138 64 | msgid "All Email log Has Been Deleted." 65 | msgstr "Visi Elektroninio pašto žurnalai buvo Ištrinti." 66 | 67 | #: email-log.php:140 68 | msgid "An Error Has Occured While Deleting All Email Logs" 69 | msgstr "Įvyko Klaida, Ištrinant Visus Elektroninio pašto Žurnalo Įrašus" 70 | 71 | #: email-log.php:174 72 | #: email-log.php:311 73 | #: email-log.php:346 74 | #: email-log.php:430 75 | msgid "ID" 76 | msgstr "Identifikatorius" 77 | 78 | #: email-log.php:178 79 | #: email-log.php:431 80 | #: email-log.php:480 81 | msgid "To Email" 82 | msgstr "Į Elektroninį paštą" 83 | 84 | #: email-log.php:182 85 | #: email-log.php:314 86 | #: email-log.php:349 87 | #: email-log.php:432 88 | #: email-log.php:482 89 | msgid "Subject" 90 | msgstr "Antraštė" 91 | 92 | #: email-log.php:187 93 | #: email-log.php:433 94 | msgid "Date" 95 | msgstr "Data" 96 | 97 | #: email-log.php:194 98 | #: email-log.php:437 99 | msgid "Ascending" 100 | msgstr "Didėjanti" 101 | 102 | #: email-log.php:199 103 | #: email-log.php:438 104 | msgid "Descending" 105 | msgstr "Mažėjanti" 106 | 107 | #: email-log.php:248 108 | msgid "Email Log Settings" 109 | msgstr "Email Log Nuostatos" 110 | 111 | #: email-log.php:249 112 | #, php-format 113 | msgid "Displaying %s to %s of %s Email log entries." 114 | msgstr "Rodoma %s iki %s%s Elektroninio pašto žurnalo įrašų." 115 | 116 | #: email-log.php:250 117 | #, php-format 118 | msgid "Sorted by %s in %s order." 119 | msgstr "Išrikiuota pagal %s po %ser tvarką." 120 | 121 | #: email-log.php:261 122 | #: email-log.php:361 123 | msgid "Previous Page" 124 | msgstr "Ankstesnis Puslapis" 125 | 126 | #: email-log.php:268 127 | #: email-log.php:368 128 | #, php-format 129 | msgid "Pages (%s): " 130 | msgstr "Puslapiai (%s):" 131 | 132 | #: email-log.php:271 133 | #: email-log.php:371 134 | msgid "Go to First Page" 135 | msgstr "Eiti į Pirmąjį Puslapį" 136 | 137 | #: email-log.php:271 138 | #: email-log.php:371 139 | msgid "First" 140 | msgstr "Pirmas" 141 | 142 | #: email-log.php:274 143 | #: email-log.php:286 144 | #: email-log.php:374 145 | #: email-log.php:386 146 | msgid "Go to Page" 147 | msgstr "Eiti į Puslapį" 148 | 149 | #: email-log.php:281 150 | #: email-log.php:381 151 | msgid "Page" 152 | msgstr "Puslapis" 153 | 154 | #: email-log.php:289 155 | #: email-log.php:389 156 | msgid "Go to Last Page" 157 | msgstr "Eiti į Paskutinį Puslapį" 158 | 159 | #: email-log.php:289 160 | #: email-log.php:389 161 | msgid "Last" 162 | msgstr "Paskutinis" 163 | 164 | #: email-log.php:296 165 | #: email-log.php:396 166 | msgid "Next Page" 167 | msgstr "Sekantis Puslapis" 168 | 169 | #: email-log.php:312 170 | #: email-log.php:347 171 | msgid "Date / Time" 172 | msgstr "Data / Laikas" 173 | 174 | #: email-log.php:313 175 | #: email-log.php:348 176 | msgid "To" 177 | msgstr "Į" 178 | 179 | #: email-log.php:328 180 | #, php-format 181 | msgid "%s @ %s" 182 | msgstr "%s @ %s" 183 | 184 | #: email-log.php:340 185 | msgid "No email Logs Found" 186 | msgstr "Nerasta jokių elektroninio pašto Žurnalo įrašų" 187 | 188 | #: email-log.php:416 189 | msgid "Filter Options:" 190 | msgstr "Filtravimo Parinktys:" 191 | 192 | #: email-log.php:418 193 | msgid "ID:" 194 | msgstr "Identifikatorius:" 195 | 196 | #: email-log.php:420 197 | msgid "To Email:" 198 | msgstr "Į Elektroninį paštą:" 199 | 200 | #: email-log.php:422 201 | msgid "Subject:" 202 | msgstr "Antraštė:" 203 | 204 | #: email-log.php:427 205 | msgid "Sort Options:" 206 | msgstr "Rikiavimo Parinktys:" 207 | 208 | #: email-log.php:445 209 | #: email-log.php:447 210 | msgid "Per Page" 211 | msgstr "Puslapyje" 212 | 213 | #: email-log.php:455 214 | msgid "Go" 215 | msgstr "Eiti" 216 | 217 | #: email-log.php:469 218 | msgid "Delete Type : " 219 | msgstr "Ištrinti Tipą:" 220 | 221 | #: email-log.php:472 222 | msgid "Based on" 223 | msgstr "Pagrįsta" 224 | 225 | #: email-log.php:473 226 | msgid "All Logs" 227 | msgstr "Visi Žurnalai" 228 | 229 | #: email-log.php:478 230 | msgid "Condition:" 231 | msgstr "Sąlyga:" 232 | 233 | #: email-log.php:481 234 | msgid "or" 235 | msgstr "arba" 236 | 237 | #: email-log.php:487 238 | msgid "" 239 | "You Are About To Delete Email Logs.\\n" 240 | "This Action Is Not Reversible.\\n" 241 | "\\n" 242 | " Choose \\'Cancel\\' to stop, \\'OK\\' to delete." 243 | msgstr "" 244 | "Jūs Mėginate Ištrinti Visus Elektroninio Pašto Žurnalus. \\n" 245 | "Šio veiksmo padariniai yra neatstatomi. \\n" 246 | "\\n" 247 | "Pasirinkite \\'Cancel\\', kad sustabdytumėte procesą, \\'OK\\'. kad tęstumėte trynimą." 248 | 249 | #. Plugin URI of an extension 250 | msgid "http://sudarmuthu.com/wordpress/email-log" 251 | msgstr "http://sudarmuthu.com/wordpress/email-log" 252 | 253 | #. Description of an extension 254 | msgid "Logs every email sent through WordPress. Compatiable with WPMU too." 255 | msgstr "Į žurnalą įrašo kiekvieną per WordPress išsiųstą elektroninį laišką. Taip pat suderinamas su WPMU." 256 | 257 | #. Author of an extension 258 | msgid "Sudar" 259 | msgstr "Sudar" 260 | 261 | #. Author URI of an extension 262 | msgid "http://sudarmuthu.com/" 263 | msgstr "http://sudarmuthu.com/" 264 | 265 | -------------------------------------------------------------------------------- /include/Core/Request/LogListAction.php: -------------------------------------------------------------------------------- 1 | . 17 | * 18 | * @inheritdoc 19 | */ 20 | public function load() { 21 | add_action( 'wp_ajax_el-log-list-view-message', array( $this, 'view_log_message' ) ); 22 | 23 | add_action( 'el-log-list-delete', array( $this, 'delete_logs' ) ); 24 | add_action( 'el-log-list-delete-all', array( $this, 'delete_all_logs' ) ); 25 | add_action( 'el-log-list-manage-user-roles-changed', array( $this, 'update_capabilities_for_user_roles' ), 10, 2 ); 26 | } 27 | 28 | /** 29 | * AJAX callback for displaying email content. 30 | * 31 | * @since 2.4.0 Show Active Tab based on the Email's content type. 32 | * @since 1.6 33 | */ 34 | public function view_log_message() { 35 | if ( ! current_user_can( LogListPage::CAPABILITY ) ) { 36 | wp_die(); 37 | } 38 | 39 | $id = absint( $_GET['log_id'] ); 40 | 41 | if ( $id <= 0 ) { 42 | wp_die(); 43 | } 44 | 45 | $log_items = $this->get_table_manager()->fetch_log_items_by_id( array( $id ) ); 46 | if ( count( $log_items ) > 0 ) { 47 | $log_item = $log_items[0]; 48 | 49 | $headers = array(); 50 | if ( ! empty( $log_item['headers'] ) ) { 51 | $parser = new \EmailLog\Util\EmailHeaderParser(); 52 | $headers = $parser->parse_headers( $log_item['headers'] ); 53 | } 54 | 55 | $active_tab = '0'; 56 | if ( isset( $headers['content_type'] ) && 'text/html' === $headers['content_type'] ) { 57 | $active_tab = '1'; 58 | } 59 | 60 | ob_start(); 61 | ?> 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 87 | 88 |
:
:
:
89 | 90 |
91 |
    92 |
  • 93 |
  • 94 |
95 | 96 |
97 |
98 |
99 | 100 |
101 | el_kses_allowed_html( 'post' ) ); ?> 102 |
103 |
104 | 105 | 108 | 109 | get_table_manager()->delete_logs( $id_list ); 136 | $this->render_log_deleted_notice( $logs_deleted ); 137 | } 138 | 139 | /** 140 | * Delete all log entries. 141 | */ 142 | public function delete_all_logs() { 143 | $logs_deleted = $this->get_table_manager()->delete_all_logs(); 144 | $this->render_log_deleted_notice( $logs_deleted ); 145 | } 146 | 147 | /** 148 | * Update user role capabilities when the allowed user role list is changed. 149 | * 150 | * The capability will be removed from old user roles and added to new user roles. 151 | * 152 | * @since 2.1.0 153 | * 154 | * @param array $old_roles Old user roles. 155 | * @param array $new_roles New user roles. 156 | */ 157 | public function update_capabilities_for_user_roles( $old_roles, $new_roles ) { 158 | foreach ( $old_roles as $old_role ) { 159 | $role = get_role( $old_role ); 160 | 161 | if ( ! is_null( $role ) ) { 162 | $role->remove_cap( LogListPage::CAPABILITY ); 163 | } 164 | } 165 | 166 | foreach ( $new_roles as $new_role ) { 167 | $role = get_role( $new_role ); 168 | 169 | if ( ! is_null( $role ) ) { 170 | $role->add_cap( LogListPage::CAPABILITY ); 171 | } 172 | } 173 | } 174 | 175 | /** 176 | * Render Logs deleted notice. 177 | * 178 | * @param false|int $logs_deleted Number of entries deleted, False otherwise. 179 | */ 180 | protected function render_log_deleted_notice( $logs_deleted ) { 181 | $message = __( 'There was some problem in deleting the email logs', 'email-log' ); 182 | $type = 'error'; 183 | 184 | if ( absint( $logs_deleted ) > 0 ) { 185 | $message = sprintf( _n( '1 email log deleted.', '%s email logs deleted', $logs_deleted, 'email-log' ), $logs_deleted ); 186 | $type = 'updated'; 187 | } 188 | 189 | add_settings_error( 190 | 'log-list', 191 | 'deleted-email-logs', 192 | $message, 193 | $type 194 | ); 195 | } 196 | 197 | /** 198 | * Get TableManager instance. 199 | * 200 | * @return \EmailLog\Core\DB\TableManager TableManager instance. 201 | */ 202 | protected function get_table_manager() { 203 | $email_log = email_log(); 204 | 205 | return $email_log->table_manager; 206 | } 207 | 208 | /** 209 | * Allows `` tag in wp_kses(). 210 | * 211 | * Gets the list of allowed HTML for the `post` context. 212 | * Appends tag to the above list and returns the array. 213 | * 214 | * @since 2.3.0 215 | * 216 | * @param string $context Optional. Default `post`. The context for which to retrieve tags. 217 | * 218 | * @return array List of allowed tags and their allowed attributes. 219 | */ 220 | protected function el_kses_allowed_html( $context = 'post' ) { 221 | $allowed_tags = wp_kses_allowed_html( $context ); 222 | 223 | $allowed_tags['link'] = array( 224 | 'rel' => true, 225 | 'href' => true, 226 | 'type' => true, 227 | 'media' => true, 228 | ); 229 | 230 | return $allowed_tags; 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Email Log # 2 | **Contributors:** sudar 3 | **Tags:** email, log, log email, resend email, multisite 4 | **Requires PHP:** 5.6 5 | **Requires at least:** 4.0 6 | **Tested up to:** 6.4.2 7 | **Stable tag:** 2.4.9 8 | [![Plugin Version](https://img.shields.io/wordpress/plugin/v/email-log.svg)]() [![Total Downloads](https://img.shields.io/wordpress/plugin/dt/email-log.svg)]() [![Plugin Rating](https://img.shields.io/wordpress/plugin/r/email-log.svg)]() [![WordPress Compatibility](https://img.shields.io/wordpress/v/email-log.svg)]() [![Build Status](https://scrutinizer-ci.com/g/sudar/email-log/badges/build.png?b=master)](https://scrutinizer-ci.com/g/sudar/email-log/build-status/master) [![Code Coverage](https://scrutinizer-ci.com/g/sudar/email-log/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/sudar/email-log/?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/sudar/email-log/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/sudar/email-log/?branch=master) [![StyleCI](https://styleci.io/repos/7374859/shield?branch=master)](https://styleci.io/repos/7374859) [![License](https://img.shields.io/badge/license-GPL--2.0%2B-red.svg)](https://wordpress.org/about/license/) 9 | 10 | Log and view all outgoing emails from WordPress. Very useful if you have to debug email related problems or have to store sent emails for auditing. 11 | 12 | ## Description ## 13 | 14 | Email Log is a WordPress plugin that allows you to easily log and view all emails that were sent from WordPress. 15 | 16 | This would be very useful for debugging email related problems in your WordPress site or for storing sent emails for auditing purposes, especially on ecommerce sites that are setup with either WooCommerce or Easy Digital Downloads. 17 | 18 | You can perform advanced actions like re-sending email, automatically forwarding emails or export logs with our [premium add-ons](https://wpemaillog.com/store/?utm_campaign=Upsell&utm_medium=wporg&utm_source=readme&utm_content=store). 19 | 20 | Works with WordPress Multisite as well. 21 | ### Viewing logged emails 22 | 23 | The logged emails will be stored in a separate table and can be viewed from the admin interface. 24 | 25 | While viewing the logs, the emails can be filtered or sorted based on the date, email, subject etc. 26 | 27 | ### Deleting logged emails 28 | 29 | In the admin interface, all the logged emails can be delete in bulk or can also be selectively deleted based on date, email and subject. 30 | 31 | If you want to automatically delete the email logs after some days, then you can use the [Auto Delete Logs](https://wpemaillog.com/addons/auto-delete-logs/?utm_campaign=Upsell&utm_medium=wporg&utm_source=readme&utm_content=dl) add-on. 32 | 33 | ### Resend email (Pro addon) 34 | 35 | You can [buy the Resend email pro add-on](https://wpemaillog.com/addons/resend-email/?utm_campaign=Upsell&utm_medium=wporg&utm_source=readme&utm_content=re), 36 | which allows you to resend the email directly from the email log. 37 | 38 | The add-on allows you to modify the different fields of the email before resending it. 39 | 40 | ### More Fields (Pro addon) 41 | 42 | You can [buy the More Fields pro add-on](https://wpemaillog.com/addons/more-fields/?utm_campaign=Upsell&utm_medium=wporg&utm_source=readme&utm_content=mf), 43 | which shows additional fields in the email log page. The following are the additional fields that are added by this addon. 44 | 45 | - From 46 | - CC 47 | - BCC 48 | - Reply To 49 | - Attachment 50 | 51 | ### Forward email (Pro addon) 52 | 53 | You can [buy the Forward email pro add-on](https://wpemaillog.com/addons/more-fields/?utm_campaign=Upsell&utm_medium=wporg&utm_source=readme&utm_content=fe), 54 | which allows you to send a copy of all the emails send from WordPress to another email address. 55 | 56 | The addon allows you to choose whether you want to forward through to, cc or bcc fields. 57 | 58 | This can be extremely useful when you want to debug by analyzing the emails that are sent from WordPress. 59 | 60 | ### Export email logs (Pro addon) 61 | 62 | You can buy the [Export Email Logs add-on](https://wpemaillog.com/addons/export-logs/?utm_campaign=Upsell&utm_medium=wporg&utm_source=readme&utm_content=el), which allows you to export the email logs as a csv file for further processing or record keeping. 63 | 64 | ### Cleaning up db on uninstall 65 | 66 | As [recommended by Ozh][1], the Plugin has an uninstall hook which will clean up the database and options when the Plugin is uninstalled. 67 | 68 | [1]: https://sudarmuthu.com/blog/lessons-from-wordpress-plugin-competition/ 69 | 70 | ### Documentation 71 | 72 | You can find fully searchable documentation about using the plugin in the [doc section of the Email Log](https://wpemaillog.com/docs/) website. 73 | 74 | ### Development 75 | 76 | The development of the Plugin happens over at [github](http://github.com/sudar/email-log). 77 | 78 | If you want to contribute to the Plugin, [fork the project at github](http://github.com/sudar/email-log) and send me a pull request. 79 | 80 | If you are not familiar with either git or Github then refer to this [guide to see how fork and send pull request](http://sudarmuthu.com/blog/contributing-to-project-hosted-in-github). 81 | 82 | ### Support 83 | 84 | - If you have a question about usage of the free plugin or need help to troubleshoot, then post in [WordPress forums](https://wordpress.org/support/plugin/email-log). 85 | - If you have a question about any of the pro add-ons or have a feature request then post them in the [support section of our site](https://wpemaillog.com/support/?utm_campaign=Upsell&utm_medium=wporg&utm_source=readme&utm_content=support). 86 | - If you have any development related questions, then post them as [github issues](https://github.com/sudar/email-log/issues) 87 | 88 | ## Translation ## 89 | 90 | The Plugin currently has translations for the following languages. 91 | 92 | * German (Thanks Frank) 93 | * Lithuanian (Thanks Vincent G) 94 | * Dutch (Thanks Zjan Preijde) 95 | 96 | The pot file is available with the Plugin. 97 | 98 | If you are willing to do translation for the Plugin, use the pot file to create the .po files for your language and let me know. 99 | 100 | I will add it to the Plugin after giving credit to you. 101 | 102 | ## Installation ## 103 | 104 | ### Normal WordPress installations 105 | 106 | Extract the zip file and just drop the contents in the wp-content/plugins/ directory of your WordPress installation and then activate the Plugin from Plugins page. 107 | 108 | ## Frequently Asked Questions ## 109 | 110 | ### The content of the email is not getting logged when I am using wpmandrill plugin 111 | 112 | wpmandrill plugin has a bug that prevents this plugin from logging the content of the email. 113 | 114 | More details about the bug is available at http://wordpress.org/support/topic/mandrill-is-changing-the-names-of-args-in-the-filter?replies=1. 115 | 116 | I have asked the author of the plugin to fix it and it might get fixed it the next release. 117 | 118 | Meanwhile, I have added a hack to handle this condition in v1.7.3 of my plugin. So if the content is not getting logged, then upgrade to v1.7.3. 119 | 120 | ## Screenshots ## 121 | 122 | ![](assets-wp-repo/screenshot-1.png) 123 | The above screenshot shows how the logged emails will be displayed by the Plugin 124 | 125 | ![](assets-wp-repo/screenshot-2.png) 126 | This screenshot shows how you can configure the email display screen. You can choose the fields and the number of emails per page 127 | 128 | ![](assets-wp-repo/screenshot-3.png) 129 | The above screenshot shows the HTML version (if available) of the logged email that you choose to view 130 | 131 | ![](assets-wp-repo/screenshot-4.png) 132 | The above screenshot shows the text version of the logged email that you choose to view 133 | 134 | ![](assets-wp-repo/screenshot-5.png) 135 | The above screenshot shows how you can search logged emails by date 136 | 137 | ## Readme Generator ## 138 | 139 | This Readme file was generated using wp-readme, which generates readme files for WordPress Plugins. 140 | -------------------------------------------------------------------------------- /languages/email-log-nl_NL.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Email Log WordPress Plugin 0.2\n" 4 | "Report-Msgid-Bugs-To: http://wordpress.org/tag/email-log\n" 5 | "POT-Creation-Date: 2012-04-29 17:11:23+00:00\n" 6 | "PO-Revision-Date: \n" 7 | "Last-Translator: Zjan Preijde \n" 8 | "Language-Team: Frank Weichbrodt\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "X-Poedit-Language: German\n" 13 | "X-Poedit-Country: GERMANY\n" 14 | 15 | #. #-#-#-#-# plugin.pot (Email Log 0.6) #-#-#-#-# 16 | #. Plugin Name of the plugin/theme 17 | #: email-log.php:85 18 | msgid "Email Log" 19 | msgstr "E-Mail Log" 20 | 21 | #: email-log.php:106 22 | msgid "About Plugin" 23 | msgstr "Over de plugin" 24 | 25 | #: email-log.php:108 26 | msgid "Email Log WordPress Plugin, allows you to log all emails that are sent through WordPress." 27 | msgstr "Email Log WordPress Plugin, maakt het mogelijk al je e-mails te loggen die verstuurd worden via Wordpress." 28 | 29 | #: email-log.php:115 30 | msgid "More information" 31 | msgstr "Meer informatie" 32 | 33 | #: email-log.php:116 34 | msgid "Plugin Homepage/support" 35 | msgstr "Plugin Homepage/support" 36 | 37 | #: email-log.php:117 38 | msgid "Plugin author's blog" 39 | msgstr "Blog van plugin auteur" 40 | 41 | #: email-log.php:118 42 | msgid "Other Plugin's by Author" 43 | msgstr "Andere plugins door deze auteur" 44 | 45 | #: email-log.php:125 46 | msgid "Entries per page" 47 | msgstr "Logs per pagina" 48 | 49 | #: email-log.php:163 50 | msgid "Settings" 51 | msgstr "Instellingen" 52 | 53 | #: email-log.php:173 54 | msgid "plugin" 55 | msgstr "plugin" 56 | 57 | #: email-log.php:173 58 | msgid "Version" 59 | msgstr "Versie" 60 | 61 | #: email-log.php:173 62 | msgid "by" 63 | msgstr "door" 64 | 65 | #: email-log.php:203 66 | #: email-log.php:555 67 | #: email-log.php:578 68 | msgid "Delete Logs" 69 | msgstr "Logs verwijderen" 70 | 71 | #: email-log.php:212 72 | msgid "The selected Email Logs have been deleted." 73 | msgstr "De geselecteerde e-mail logs zijn verwijderd." 74 | 75 | #: email-log.php:214 76 | msgid "An error has occurred while deleting the selected Email logs" 77 | msgstr "Bij het verwijderen van de geselecteerde e-mail logs is er een fout opgetreden." 78 | 79 | #: email-log.php:223 80 | msgid "All Email Logs For email id %s Have Been Deleted." 81 | msgstr "Alle e-mail logs met ID %s zijn verwijderd." 82 | 83 | #: email-log.php:225 84 | msgid "An error has occurred while deleting All Email Logs For email id %s." 85 | msgstr "Bij het verwijderen van alle e-mail logs met ID %s is er een fout opgetreden." 86 | 87 | #: email-log.php:233 88 | msgid "All Email Logs With Subject %s Have Been Deleted." 89 | msgstr "Alle e-mail logs met het onderwerp %s zijn verwijderd." 90 | 91 | #: email-log.php:235 92 | msgid "An Error Has Occurred While Deleting All Email Logs With Subject %s." 93 | msgstr "Bij het verwijderen van alle e-mail logs met onderwerp %s is er een fout opgetreden." 94 | 95 | #: email-log.php:243 96 | msgid "All Email log Has Been Deleted." 97 | msgstr "Alle e-mail logs zijn verwijderd." 98 | 99 | #: email-log.php:245 100 | msgid "An Error Has Occurred While Deleting All Email Logs" 101 | msgstr "Bij het verwijderen van alle e-mail logs is er een fout opgetreden" 102 | 103 | #: email-log.php:275 104 | #: email-log.php:370 105 | #: email-log.php:452 106 | #: email-log.php:489 107 | msgid "ID" 108 | msgstr "ID" 109 | 110 | #: email-log.php:279 111 | #: email-log.php:371 112 | #: email-log.php:571 113 | msgid "To Email" 114 | msgstr "Ontvanger" 115 | 116 | #: email-log.php:283 117 | #: email-log.php:372 118 | #: email-log.php:455 119 | #: email-log.php:492 120 | #: email-log.php:573 121 | msgid "Subject" 122 | msgstr "Onderwerp" 123 | 124 | #: email-log.php:288 125 | #: email-log.php:373 126 | msgid "Date" 127 | msgstr "Datum" 128 | 129 | #: email-log.php:295 130 | #: email-log.php:377 131 | msgid "Ascending" 132 | msgstr "Oplopend" 133 | 134 | #: email-log.php:300 135 | #: email-log.php:378 136 | msgid "Descending" 137 | msgstr "Aflopend" 138 | 139 | #: email-log.php:348 140 | msgid "Email Log Settings" 141 | msgstr "E-mail log - Instellingen" 142 | 143 | #: email-log.php:356 144 | msgid "Filter Options:" 145 | msgstr "Filter Opties:" 146 | 147 | #: email-log.php:358 148 | msgid "ID:" 149 | msgstr "ID:" 150 | 151 | #: email-log.php:360 152 | msgid "To Email:" 153 | msgstr "Ontvanger:" 154 | 155 | #: email-log.php:362 156 | msgid "Subject:" 157 | msgstr "Onderwerp:" 158 | 159 | #: email-log.php:367 160 | msgid "Sort Options:" 161 | msgstr "Sorteer opties:" 162 | 163 | #: email-log.php:383 164 | msgid "Filter" 165 | msgstr "Filter" 166 | 167 | #: email-log.php:388 168 | msgid "Displaying %s to %s of %s Email log entries." 169 | msgstr "Getoond: %s tot %s van %s e-mail logs." 170 | 171 | #: email-log.php:389 172 | msgid "Sorted by %s in %s order." 173 | msgstr "Gesorteerd op %s in %se volgorde." 174 | 175 | #: email-log.php:401 176 | #: email-log.php:504 177 | msgid "Previous Page" 178 | msgstr "Vorige pagina" 179 | 180 | #: email-log.php:408 181 | #: email-log.php:511 182 | msgid "Pages (%s): " 183 | msgstr "Pagina's (%s): " 184 | 185 | #: email-log.php:411 186 | #: email-log.php:514 187 | msgid "Go to First Page" 188 | msgstr "Ga naar de eerste pagina" 189 | 190 | #: email-log.php:411 191 | #: email-log.php:514 192 | msgid "First" 193 | msgstr "Eerste" 194 | 195 | #: email-log.php:414 196 | #: email-log.php:426 197 | #: email-log.php:517 198 | #: email-log.php:529 199 | msgid "Go to Page" 200 | msgstr "Ga naar pagina" 201 | 202 | #: email-log.php:421 203 | #: email-log.php:524 204 | msgid "Page" 205 | msgstr "Pagina" 206 | 207 | #: email-log.php:429 208 | #: email-log.php:532 209 | msgid "Go to Last Page" 210 | msgstr "Ga naar laatste pagina" 211 | 212 | #: email-log.php:429 213 | #: email-log.php:532 214 | msgid "Last" 215 | msgstr "Laatste" 216 | 217 | #: email-log.php:436 218 | #: email-log.php:539 219 | msgid "Next Page" 220 | msgstr "Volgende pagina" 221 | 222 | #: email-log.php:453 223 | #: email-log.php:490 224 | msgid "Date / Time" 225 | msgstr "Datum / Tijd" 226 | 227 | #: email-log.php:454 228 | #: email-log.php:491 229 | msgid "To" 230 | msgstr "Aan" 231 | 232 | #: email-log.php:469 233 | msgid "%s @ %s" 234 | msgstr "%s @ %s" 235 | 236 | #: email-log.php:482 237 | msgid "No email Logs Found" 238 | msgstr "Geen e-mail logs gevonden" 239 | 240 | #: email-log.php:559 241 | msgid "Delete Type : " 242 | msgstr "Verwijder type:" 243 | 244 | #: email-log.php:562 245 | msgid "Selected entries" 246 | msgstr "Geselecteerde logs" 247 | 248 | #: email-log.php:563 249 | msgid "Based on" 250 | msgstr "Gebaseerd op" 251 | 252 | #: email-log.php:564 253 | msgid "All Logs" 254 | msgstr "Alle logs" 255 | 256 | #: email-log.php:569 257 | msgid "Condition:" 258 | msgstr "Voorwaarde:" 259 | 260 | #: email-log.php:572 261 | msgid "or" 262 | msgstr "of" 263 | 264 | #: email-log.php:578 265 | msgid "" 266 | "You Are About To Delete Email Logs.\\n" 267 | "This Action Is Not Reversible.\\n" 268 | "\\n" 269 | " Choose \\'Cancel\\' to stop, \\'OK\\' to delete." 270 | msgstr "" 271 | "Je gaat je e-mail logs verwijderen.\\n" 272 | "Deze actie kan niet ongedaan gemaakt worden.\\n" 273 | 274 | #. Plugin URI of the plugin/theme 275 | msgid "http://sudarmuthu.com/wordpress/email-log" 276 | msgstr "http://sudarmuthu.com/wordpress/email-log" 277 | 278 | #. Description of the plugin/theme 279 | msgid "Logs every email sent through WordPress. Compatiable with WPMU too." 280 | msgstr "Logt alle door WordPress verzonden e-mail. Compatibel met WPMU." 281 | 282 | #. Author of the plugin/theme 283 | msgid "Sudar" 284 | msgstr "Sudar" 285 | 286 | #. Author URI of the plugin/theme 287 | msgid "http://sudarmuthu.com/" 288 | msgstr "http://sudarmuthu.com/" 289 | 290 | #~ msgid "Per Page" 291 | #~ msgstr "Per pagina" 292 | 293 | #~ msgid "Go" 294 | #~ msgstr "Ga" 295 | -------------------------------------------------------------------------------- /include/Addon/License/BaseLicense.php: -------------------------------------------------------------------------------- 1 | edd_api = $edd_api; 44 | } 45 | 46 | /** 47 | * Set the license Key. 48 | * 49 | * @param string $license_key License Key. 50 | */ 51 | public function set_license_key( $license_key ) { 52 | $this->license_key = $license_key; 53 | } 54 | 55 | /** 56 | * Get the license key. 57 | * 58 | * @return string|null License Key. 59 | */ 60 | public function get_license_key() { 61 | return $this->license_key; 62 | } 63 | 64 | /** 65 | * Set add-on name. 66 | * 67 | * @param string $addon_name Add-on Name. 68 | */ 69 | public function set_addon_name( $addon_name ) { 70 | $this->addon_name = $addon_name; 71 | } 72 | 73 | /** 74 | * Get the add-on name. 75 | * 76 | * @return string Add-on name. 77 | */ 78 | public function get_addon_name() { 79 | return $this->addon_name; 80 | } 81 | 82 | /** 83 | * Get the expiry date of the license. 84 | * 85 | * @return false|string Expiry date in `yyyy-mm-dd hh:mm:ss` format if license is valid, False otherwise. 86 | */ 87 | public function get_expiry_date() { 88 | if ( ! empty( $this->license_data ) && isset( $this->license_data->expires ) ) { 89 | return $this->license_data->expires; 90 | } 91 | 92 | return false; 93 | } 94 | 95 | /** 96 | * Has the bundle license expired? 97 | * 98 | * @since 2.3.0 99 | * 100 | * @return bool True if expired, False otherwise. 101 | */ 102 | public function has_expired() { 103 | $is_valid = $this->is_valid(); 104 | 105 | if ( ! $is_valid ) { 106 | return true; 107 | } 108 | 109 | $expiry_date = $this->get_expiry_date(); 110 | 111 | if ( ! $expiry_date ) { 112 | return true; 113 | } 114 | 115 | return ( strtotime( $expiry_date ) < time() ); 116 | } 117 | 118 | /** 119 | * Is the license activated and valid? 120 | * 121 | * @since 2.3.0 Moved to BaseLicense class. 122 | * 123 | * @return bool True if license is active, False otherwise. 124 | */ 125 | public function is_valid() { 126 | if ( ! $this->license_data instanceof \stdClass || ! isset( $this->license_data->license ) ) { 127 | return false; 128 | } 129 | 130 | return ( 'valid' === $this->license_data->license ); 131 | } 132 | 133 | /** 134 | * Get the renewal link for bundle license. 135 | * 136 | * @since 2.3.0 137 | * 138 | * @return string Renewal link. 139 | */ 140 | public function get_renewal_link() { 141 | $license_key = $this->get_license_key(); 142 | 143 | if ( empty( $license_key ) ) { 144 | return 'https://wpemaillog.com/store/?utm_campaign=Renewal&utm_medium=wpadmin&utm_source=renewal-notice'; 145 | } 146 | 147 | return sprintf( 'https://wpemaillog.com/checkout/?edd_license_key=%s&utm_campaign=Renewal&utm_medium=wpadmin&utm_source=renewal-notice', $license_key ); 148 | } 149 | 150 | /** 151 | * Activate License by calling EDD API. 152 | * The license data returned by API is stored in an option. 153 | * 154 | * @throws \Exception In case of communication errors or License Issues. 155 | * 156 | * @return object API Response JSON Object. 157 | */ 158 | public function activate() { 159 | $response = $this->edd_api->activate_license( $this->get_license_key(), $this->get_addon_name() ); 160 | 161 | if ( $response->success && 'valid' === $response->license ) { 162 | $response->license_key = $this->get_license_key(); 163 | 164 | $this->store( $response ); 165 | 166 | return $response; 167 | } 168 | 169 | switch ( $response->error ) { 170 | case 'expired': 171 | $message = sprintf( 172 | /* translators: 1 License expiry date, 2 License Renewal link */ 173 | __( 'Your license key expired on %1$s. Please renew it to receive automatic updates and support.', 'email-log' ), 174 | date_i18n( get_option( 'date_format' ), strtotime( $response->expires, current_time( 'timestamp' ) ) ), 175 | 'https://wpemaillog.com/checkout/?edd_license_key=' . $this->get_license_key() . '&utm_campaign=Renewal&utm_medium=wpadmin&utm_source=activation-failed' 176 | ); 177 | break; 178 | 179 | case 'revoked': 180 | $message = __( 'Your license key has been disabled.', 'email-log' ); 181 | break; 182 | 183 | case 'missing': 184 | $message = __( 'Your license key is invalid.', 'email-log' ); 185 | break; 186 | 187 | case 'invalid': 188 | case 'site_inactive': 189 | $message = __( 'Your license is not active for this URL.', 'email-log' ); 190 | break; 191 | 192 | case 'item_name_mismatch': 193 | /* translators: 1 Add-on name */ 194 | $message = sprintf( __( 'Your license key is not valid for %s.', 'email-log' ), $this->get_addon_name() ); 195 | break; 196 | 197 | case 'no_activations_left': 198 | $message = sprintf( 199 | /* translators: 1 License Upgrade link */ 200 | __( 'Your license key has reached its activation limit. Please upgrade your license.', 'email-log' ), 201 | 'https://wpemaillog.com/account/?utm_campaign=Upgrade&utm_medium=wpadmin&utm_source=activation-failed' 202 | ); 203 | break; 204 | 205 | default: 206 | $message = __( 'An error occurred, please try again.', 'email-log' ); 207 | break; 208 | } 209 | 210 | throw new \Exception( $message ); 211 | } 212 | 213 | /** 214 | * Deactivate the license by calling EDD API. 215 | * The stored license data will be cleared. 216 | * 217 | * @throws \Exception In case of communication errors. 218 | * 219 | * @return object API Response JSON object. 220 | */ 221 | public function deactivate() { 222 | $response = $this->edd_api->deactivate_license( $this->get_license_key(), $this->get_addon_name() ); 223 | 224 | if ( $response->success && 'deactivated' === $response->license ) { 225 | $this->clear(); 226 | 227 | return $response; 228 | } 229 | 230 | if ( $response->expires < time() ) { 231 | // license has expired. Expired license can't be de-activated. So let's just clear it. 232 | $this->clear(); 233 | 234 | return $response; 235 | } 236 | 237 | $message = __( 'An error occurred, please try again.', 'email-log' ); 238 | 239 | if ( isset( $response->error ) ) { 240 | $message .= ' ' . $response->error; 241 | } 242 | 243 | throw new \Exception( $message ); 244 | } 245 | 246 | /** 247 | * Get version information by calling EDD API. 248 | * // TODO: Currently not used. Will be removed eventually. 249 | * 250 | * @throws \Exception In case of communication errors. 251 | * 252 | * @return object API Response JSON Object. 253 | */ 254 | public function get_version() { 255 | $response = $this->edd_api->get_version( $this->get_license_key(), $this->get_addon_name() ); 256 | 257 | if ( isset( $response->new_version ) && ! isset( $response->msg ) ) { 258 | return $response; 259 | } 260 | 261 | $message = __( 'An error occurred, please try again', 'email-log' ) . $response->error; 262 | 263 | throw new \Exception( $message ); 264 | } 265 | 266 | /** 267 | * Load the license data from DB option. 268 | */ 269 | public function load() { 270 | $this->license_data = get_option( $this->get_option_name(), null ); 271 | } 272 | 273 | /** 274 | * Store License data in DB option. 275 | * 276 | * @access protected 277 | * 278 | * @param object $license_data License data. 279 | */ 280 | protected function store( $license_data ) { 281 | $this->license_data = $license_data; 282 | update_option( $this->get_option_name(), $license_data ); 283 | } 284 | 285 | /** 286 | * Clear stored license data. 287 | * 288 | * @access protected 289 | */ 290 | protected function clear() { 291 | $this->license_data = null; 292 | $this->license_key = null; 293 | delete_option( $this->get_option_name() ); 294 | } 295 | } 296 | --------------------------------------------------------------------------------