logger->error($error); return $error; } self::$block_dirs[] = $dir; return true; } } /** * @property int $id The list unique identifier * @property string $name The list name * @property bool $forced If the list must be added to every new subscriber * @property int $status When and how the list is visible to the subscriber - see constants * @property bool $checked If it must be pre-checked on subscription form * @property array $languages The list of language used to pre-assign this list */ abstract class TNP_List { const STATUS_PRIVATE = 0; const STATUS_PUBLIC = 2; const STATUS_PROFILE_ONLY = 1; const STATUS_HIDDEN = 3; // Public but never show (can be set with a hidden form field) } /** * @property int $id The list unique identifier * @property string $name The list name * @property int $status When and how the list is visible to the subscriber - see constants */ abstract class TNP_Profile { const STATUS_PRIVATE = 0; const STATUS_PUBLIC = 2; const STATUS_PROFILE_ONLY = 1; const STATUS_HIDDEN = 3; // Public but never show (can be set with a hidden form field) } /** * @property int $id The subscriber unique identifier * @property string $email The subscriber email * @property string $name The subscriber name or first name * @property string $surname The subscriber last name * @property string $status The subscriber status * @property string $language The subscriber language code 2 chars lowercase */ abstract class TNP_User { const STATUS_CONFIRMED = 'C'; const STATUS_NOT_CONFIRMED = 'S'; const STATUS_UNSUBSCRIBED = 'U'; const STATUS_BOUNCED = 'B'; } /** * @property int $id The subscriber unique identifier * @property string $subject The subscriber email * @property string $message The subscriber name or first name * @property string $track The subscriber last name * @property array $options The subscriber status * */ abstract class TNP_Email { } /** * @property string $id Theme identifier * @property string $dir Absolute path to the theme folder * @property string $name Theme name */ class TNP_Theme { var $dir; var $name; public function get_defaults() { @include $this->dir . '/theme-defaults.php'; if (!isset($theme_defaults) || !is_array($theme_defaults)) return array(); return $theme_defaults; } } class NewsletterAddon { var $logger; var $admin_logger; var $name; var $options; var $version; public function __construct($name, $version = '0.0.0') { $this->name = $name; $this->version = $version; if (is_admin()) { $old_version = get_option('newsletter_' . $name . '_version'); if ($version != $old_version) { $this->upgrade($old_version === false); update_option('newsletter_' . $name . '_version', $version, false); } } add_action('newsletter_init', array($this, 'init')); } function upgrade($first_install = false) { } function init() { } /** * * @return NewsletterLogger */ function get_logger() { if (!$this->logger) { $this->logger = new NewsletterLogger($this->name); } return $this->logger; } function get_admin_logger() { if (!$this->admin_logger) { $this->admin_logger = new NewsletterLogger($this->name . '-admin'); } return $this->admin_logger; } function setup_options() { if ($this->options) return; $this->options = get_option('newsletter_' . $this->name, array()); } function save_options($options) { update_option('newsletter_' . $this->name, $options); $this->setup_options(); } function merge_defaults($defaults) { $options = get_option('newsletter_' . $this->name, array()); $options = array_merge($defaults, $options); $this->save_options($options); } /** * @global wpdb $wpdb * @param string $query */ function query($query) { global $wpdb; $r = $wpdb->query($query); if ($r === false) { $logger = $this->get_logger(); $logger->fatal($query); $logger->fatal($wpdb->last_error); } return $r; } } class NewsletterMailerAddon extends NewsletterAddon { var $enabled = false; function __construct($name, $version = '0.0.0') { parent::__construct($name, $version); $this->setup_options(); $this->enabled = !empty($this->options['enabled']); } function init() { parent::init(); add_action('newsletter_register_mailer', function () { if ($this->enabled) { Newsletter::instance()->register_mailer($this->get_mailer()); } }); } /** * * @return NewsletterMailer */ function get_mailer() { return null; } function get_last_run() { return get_option('newsletter_' . $this->name . '_last_run', 0); } function save_last_run($time) { update_option('newsletter_' . $this->name . '_last_run', $time); } function save_options($options) { parent::save_options($options); $this->enabled = !empty($options['enabled']); } static function get_test_message($to, $subject = '') { $message = new TNP_Mailer_Message(); $message->to = $to; $message->to_name = ''; $message->body = "\n"; $message->body .= "This is the rich text (HTML) version of a test message.
\n"; $message->body .= "This is a bold text\n"; $message->body .= "This is a link to www.thenewsletterplugin.com\n"; $message->body_text = 'This is the TEXT version of a test message. You should see this message only if you email client does not support the rich text (HTML) version.'; $message->headers['X-Newsletter-Email-Id'] = '0'; if (empty($subject)) { $message->subject = '[' . get_option('blogname') . '] Test message from Newsletter (' . date(DATE_ISO8601) . ')'; } else { $message->subject = $subject; } $message->from = Newsletter::instance()->options['sender_email']; $message->from_name = Newsletter::instance()->options['sender_name']; return $message; } function get_test_messages($to, $count) { $messages = array(); for ($i = 0; $i < $count; $i++) { $messages[] = self::get_test_message($to, '[' . get_option('blogname') . '] Test message ' . ($i + 1) . ' from Newsletter (' . date(DATE_ISO8601) . ')'); } return $messages; } } /** */ class NewsletterMailer { const ERROR_GENERIC = '1'; const ERROR_FATAL = '2'; /* @var NewsletterLogger */ var $logger; var $name; var $options; private $delta; protected $batch_size = 1; public function __construct($name, $options = array()) { $this->name = $name; $this->options = $options; } public function get_name() { return $this->name; } public function get_description() { return $this->name; } public function get_batch_size() { return $this->batch_size; } function send_with_stats($message) { $this->delta = microtime(true); $r = $this->send($message); $this->delta = microtime(true) - $this->delta; return $r; } /** * * @param TNP_Mailer_Message $message * @return bool|WP_Error */ public function send($message) { $message->error = 'No mailing system available'; return new WP_Error(self::ERROR_FATAL, 'No mailing system available'); } public function send_batch_with_stats($messages) { $this->delta = microtime(true); $r = $this->send_batch($messages); $this->delta = microtime(true) - $this->delta; return $r; } function get_capability() { return (int) (3600 * $this->batch_size / $this->delta); } /** * * @param TNP_Mailer_Message[] $messages * @return bool|WP_Error */ public function send_batch($messages) { // We should not get there is the batch size is one, the caller should use "send()". We can get // there if the array of messages counts to one, since could be the last of a series of chunks. if ($this->batch_size == 1 || count($messages) == 1) { //$this->get_logger()->debug('Caso 1 messaggio'); $last_result = true; foreach ($messages as $message) { $r = $this->send($message); if (is_wp_error($r)) { $last_result = $r; } } return $last_result; } // We should always get there if (count($messages) <= $this->batch_size) { //$this->get_logger()->debug('Caso batch esatto'); return $this->send_chunk($messages); } //$this->get_logger()->debug('Caso bach troppo grande'); // We should not get here, since it is not optimized $chunks = array_chunk($message, $this->batch_size); $last_result = true; foreach ($chunks as $chunk) { $r = $this->send_chunk($chunk); if (is_wp_error($r)) { $last_result = $r; } } return $last_result; } protected function send_chunk($messages) { $last_result = true; foreach ($messages as $message) { $r = $this->send($message); if (is_wp_error($r)) { $last_result = $r; } } return $last_result; } /** * * @return NewsletterLogger */ function get_logger() { if ($this->logger) { return $this->logger; } $this->logger = new NewsletterLogger('mailer-' . $this->name); return $this->logger; } /** * * @param TNP_Mailer_Message $message * @return bool|WP_Error */ public function enqueue(TNP_Mailer_Message $message) { // Optimization when there is no queue if ($this->queue_max == 0) { $r = $this->send($message); return $r; } $this->queue[] = $message; if (count($this->queue) >= $this->queue_max) { return $this->flush(); } return true; } public function flush() { $undelivered = array(); foreach ($this->queue as $message) { $r = $this->deliver($message); if (is_wp_error($r)) { $message->error = $r; $undelivered[] = $message; } } $this->queue = array(); if ($undelivered) { return new WP_Error(self::ERROR_GENERAL, 'Error while flushing messages', $undelivered); } return true; } /** * Original mail function simulation for compatibility. * @deprecated * * @param string $to * @param string $subject * @param array $message * @param array $headers * @param bool $enqueue * @param type $from Actually ignored * @return type */ public function mail($to, $subject, $message, $headers = null, $enqueue = false, $from = false) { $mailer_message = new TNP_Mailer_Message(); $mailer_message->to = $to; $mailer_message->subject = $subject; $mailer_message->headers = $headers; $mailer_message->body = $message['html']; $mailer_message->body_text = $message['text']; if ($enqueue) { return !is_wp_error($this->enqueue($mailer_message)); } return !is_wp_error($this->send($mailer_message)); } function save_last_run($time) { update_option($this->prefix . '_last_run', $time); } function get_last_run() { return (int) get_option($this->prefix . '_last_run', 0); } } /** * @property string $to * @property string $subject * @property string $body * @property array $headers * @property string $from * @property string $from_name */ class TNP_Mailer_Message { var $to_name = ''; var $headers = array(); var $user_id = 0; var $email_id = 0; var $error = ''; var $subject = ''; var $body = ''; var $body_text = ''; } class NewsletterModule { /** * @var NewsletterLogger */ var $logger; /** * @var NewsletterStore */ var $store; /** * The main module options * @var array */ var $options; /** * @var string The module name */ var $module; /** * The module version * @var string */ var $version; var $old_version; /** * Prefix for all options stored on WordPress options table. * @var string */ var $prefix; /** * @var NewsletterThemes */ var $themes; var $components; function __construct($module, $version, $module_id = null, $components = array()) { $this->module = $module; $this->version = $version; $this->prefix = 'newsletter_' . $module; array_unshift($components, ''); $this->components = $components; $this->logger = new NewsletterLogger($module); $this->options = $this->get_options(); $this->store = NewsletterStore::singleton(); //$this->logger->debug($module . ' constructed'); // Version check if (is_admin()) { $this->old_version = get_option($this->prefix . '_version', '0.0.0'); if ($this->old_version == '0.0.0') { require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); $this->first_install(); update_option($this->prefix . "_first_install_time", time(), FALSE); } if (strcmp($this->old_version, $this->version) != 0) { require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); $this->logger->info('Version changed from ' . $this->old_version . ' to ' . $this->version); // Do all the stuff for this version change $this->upgrade(); update_option($this->prefix . '_version', $this->version); } add_action('admin_menu', array($this, 'admin_menu')); } } /** * * @global wpdb $wpdb * @param string $query */ function query($query) { global $wpdb; $this->logger->debug($query); $r = $wpdb->query($query); if ($r === false) { $this->logger->fatal($wpdb->last_error); } return $r; } function get_results($query) { global $wpdb; $r = $wpdb->get_results($query); if ($r === false) { $logger = $this->get_logger(); $logger->fatal($query); $logger->fatal($wpdb->last_error); } return $r; } /** * * @global wpdb $wpdb * @param string $table * @param array $data */ function insert($table, $data) { global $wpdb; $this->logger->debug("inserting into table $table"); $r = $wpdb->insert($table, $data); if ($r === false) { $this->logger->fatal($wpdb->last_error); } } function first_install() { $this->logger->debug('First install'); } /** * Does a basic upgrade work, checking if the options is already present and if not (first * installation), recovering the defaults, saving them on database and initializing the * internal $options. */ function upgrade() { foreach ($this->components as $component) { $this->logger->debug('Upgrading component ' . $component); $this->init_options($component); } } function init_options($component = '', $autoload = true) { global $wpdb; $default_options = $this->get_default_options($component); $options = $this->get_options($component); $options = array_merge($default_options, $options); $this->save_options($options, $component, $autoload); } function upgrade_query($query) { global $wpdb, $charset_collate; $this->logger->info('upgrade_query> Executing ' . $query); $suppress_errors = $wpdb->suppress_errors(true); $wpdb->query($query); if ($wpdb->last_error) { $this->logger->debug($wpdb->last_error); } $wpdb->suppress_errors($suppress_errors); } /** Returns a prefix to be used for option names and other things which need to be uniquely named. The parameter * "sub" should be used when a sub name is needed for another set of options or like. * * @param string $sub * @return string The prefix for names */ function get_prefix($sub = '', $language = '') { return $this->prefix . (!empty($sub) ? '_' : '') . $sub . (!empty($language) ? '_' : '') . $language; } /** * Returns the options of a module, if not found an empty array. */ function get_options($sub = '', $language = '') { $options = get_option($this->get_prefix($sub, $language), array()); // Protection against scarmled database... if (!is_array($options)) { $options = array(); } if ($language) { $main_options = get_option($this->get_prefix($sub)); // Protection against scarmled database... if (!is_array($main_options)) $main_options = array(); //$options = array_merge($main_options, array_filter($options)); $options = array_merge($main_options, $options); } return $options; } function get_default_options($sub = '') { if (!empty($sub)) { $sub = '-' . $sub; } $file = NEWSLETTER_DIR . '/' . $this->module . '/defaults' . $sub . '.php'; if (file_exists($file)) { @include $file; } if (!isset($options) || !is_array($options)) { return array(); } return $options; } function reset_options($sub = '') { $this->save_options(array_merge($this->get_options($sub), $this->get_default_options($sub)), $sub); return $this->get_options($sub); } /** * Saves the module options (or eventually a subset names as per parameter $sub). $options * should be an array (even if it can work with non array options. * The internal module options variable IS initialized with those new options only for the main * options (empty $sub parameter). * If the options contain a "theme" value, the theme-related options contained are saved as well * (used by some modules). * * @param array $options * @param string $sub */ function save_options($options, $sub = '', $autoload = null, $language = '') { update_option($this->get_prefix($sub, $language), $options, $autoload); if (empty($sub) && empty($language)) { $this->options = $options; if (isset($this->themes) && isset($options['theme'])) { $this->themes->save_options($options['theme'], $options); } } } function delete_options($sub = '') { delete_option($this->get_prefix($sub)); if (empty($sub)) { $this->options = array(); } } function merge_options($options, $sub = '', $language = '') { if (!is_array($options)) { $options = array(); } $old_options = $this->get_options($sub, $language); $this->save_options(array_merge($old_options, $options), $sub, null, $language); } function backup_options($sub) { $options = $this->get_options($sub); update_option($this->get_prefix($sub) . '_backup', $options, false); } function get_last_run($sub = '') { return get_option($this->get_prefix($sub) . '_last_run', 0); } /** * Save the module last run value. Used to store a timestamp for some modules, * for example the Feed by Mail module. * * @param int $time Unix timestamp (as returned by time() for example) * @param string $sub Sub module name (default empty) */ function save_last_run($time, $sub = '') { update_option($this->get_prefix($sub) . '_last_run', $time); } /** * Sums $delta seconds to the last run time. * @param int $delta Seconds * @param string $sub Sub module name (default empty) */ function add_to_last_run($delta, $sub = '') { $time = $this->get_last_run($sub); $this->save_last_run($time + $delta, $sub); } /** * Checks if the semaphore of that name (for this module) is still red. If it is active the method * returns false. If it is not active, it will be activated for $time seconds. * * Since this method activate the semaphore when called, it's name is a bit confusing. * * @param string $name Sempahore name (local to this module) * @param int $time Max time in second this semaphore should stay red * @return boolean False if the semaphore is red and you should not proceed, true is it was not active and has been activated. */ function check_transient($name, $time) { if ($time < 60) $time = 60; //usleep(rand(0, 1000000)); if (($value = get_transient($this->get_prefix() . '_' . $name)) !== false) { list($t, $v) = explode(';', $value, 2); $this->logger->error('Blocked by transient ' . $this->get_prefix() . '_' . $name . ' set ' . (time() - $t) . ' seconds ago by ' . $v); return false; } //$ip = ''; //gethostbyname(gethostname()); $value = time() . ";" . ABSPATH . ';' . gethostname(); set_transient($this->get_prefix() . '_' . $name, $value, $time); return true; } function delete_transient($name = '') { delete_transient($this->get_prefix() . '_' . $name); } /** Returns a random token of the specified size (or 10 characters if size is not specified). * * @param int $size * @return string */ static function get_token($size = 10) { return substr(md5(rand()), 0, $size); } /** * Adds query string parameters to an URL checing id there are already other parameters. * * @param string $url * @param string $qs The part of query-string to add (param1=value1¶m2=value2...) * @param boolean $amp If the method must use the & instead of the plain & (default true) * @return string */ static function add_qs($url, $qs, $amp = true) { if (strpos($url, '?') !== false) { if ($amp) return $url . '&' . $qs; else return $url . '&' . $qs; } else return $url . '?' . $qs; } /** * Returns the email address normalized, lowercase with no spaces. If it's not a valid email * returns false. */ static function normalize_email($email) { if (!is_string($email)) return false; $email = strtolower(trim($email)); if (!is_email($email)) { return false; } //$email = apply_filters('newsletter_normalize_email', $email); return $email; } static function normalize_name($name) { $name = str_replace(';', ' ', $name); $name = strip_tags($name); return $name; } static function normalize_sex($sex) { $sex = trim(strtolower($sex)); if ($sex != 'f' && $sex != 'm') { $sex = 'n'; } return $sex; } static function is_email($email, $empty_ok = false) { if (!is_string($email)) return false; $email = strtolower(trim($email)); if ($email == '') { return $empty_ok; } if (!is_email($email)) { return false; } // TODO: To be moved on the subscription module and make configurable if (strpos($email, 'mailinator.com') !== false) { return false; } if (strpos($email, 'guerrillamailblock.com') !== false) { return false; } if (strpos($email, 'emailtemporanea.net') !== false) { return false; } return true; } /** * Converts a GMT date from mysql (see the posts table columns) into a timestamp. * * @param string $s GMT date with format yyyy-mm-dd hh:mm:ss * @return int A timestamp */ static function m2t($s) { // TODO: use the wordpress function I don't remember the name $s = explode(' ', $s); $d = explode('-', $s[0]); $t = explode(':', $s[1]); return gmmktime((int) $t[0], (int) $t[1], (int) $t[2], (int) $d[1], (int) $d[2], (int) $d[0]); } static function format_date($time) { if (empty($time)) { return '-'; } return gmdate(get_option('date_format') . ' ' . get_option('time_format'), $time + get_option('gmt_offset') * 3600); } static function format_time_delta($delta) { $days = floor($delta / (3600 * 24)); $hours = floor(($delta % (3600 * 24)) / 3600); $minutes = floor(($delta % 3600) / 60); $seconds = floor(($delta % 60)); $buffer = $days . ' days, ' . $hours . ' hours, ' . $minutes . ' minutes, ' . $seconds . ' seconds'; return $buffer; } /** * Formats a scheduler returned "next execution" time, managing negative or false values. Many times * used in conjuction with "last run". * * @param string $name The scheduler name * @return string */ static function format_scheduler_time($name) { $time = wp_next_scheduled($name); if ($time === false) { return 'No next run scheduled'; } $delta = $time - time(); // If less 10 minutes late it can be a cron problem but now it is working if ($delta < 0 && $delta > -600) { return 'Probably running now'; } else if ($delta <= -600) { return 'It seems the cron system is not working. Reload the page to see if this message change.'; } return 'Runs in ' . self::format_time_delta($delta); } static function date($time = null, $now = false, $left = false) { if (is_null($time)) { $time = time(); } if ($time == false) { $buffer = 'none'; } else { $buffer = gmdate(get_option('date_format') . ' ' . get_option('time_format'), $time + get_option('gmt_offset') * 3600); } if ($now) { $buffer .= ' (now: ' . gmdate(get_option('date_format') . ' ' . get_option('time_format'), time() + get_option('gmt_offset') * 3600); $buffer .= ')'; } if ($left) { $buffer .= ', ' . gmdate('H:i:s', $time - time()) . ' left'; } return $buffer; } /** * Return an array of array with on first element the array of recent post and on second element the array * of old posts. * * @param array $posts * @param int $time */ static function split_posts(&$posts, $time = 0) { if ($time < 0) { return array_chunk($posts, ceil(count($posts) / 2)); } $result = array(array(), array()); if (empty($posts)) return $result; foreach ($posts as &$post) { if (self::is_post_old($post, $time)) $result[1][] = $post; else $result[0][] = $post; } return $result; } static function is_post_old(&$post, $time = 0) { return self::m2t($post->post_date_gmt) <= $time; } static function get_post_image($post_id = null, $size = 'thumbnail', $alternative = null) { global $post; if (empty($post_id)) $post_id = $post->ID; if (empty($post_id)) return $alternative; $image_id = function_exists('get_post_thumbnail_id') ? get_post_thumbnail_id($post_id) : false; if ($image_id) { $image = wp_get_attachment_image_src($image_id, $size); return $image[0]; } else { $attachments = get_children(array('post_parent' => $post_id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID')); if (empty($attachments)) { return $alternative; } foreach ($attachments as $id => $attachment) { $image = wp_get_attachment_image_src($id, $size); return $image[0]; } } } /** * Cleans up a text containing url tags with appended the absolute URL (due to * the editor behavior) moving back them to the simple form. */ static function clean_url_tags($text) { $text = str_replace('%7B', '{', $text); $text = str_replace('%7D', '}', $text); // Only tags which are {*_url} $text = preg_replace("/[\"']http[^\"']+(\\{[^\\}]+_url\\})[\"']/i", "\"\\1\"", $text); return $text; } function get_styles() { $list = array('' => 'none'); $dir = NEWSLETTER_DIR . '/' . $this->module . '/styles'; $handle = @opendir($dir); if ($handle !== false) { while ($file = readdir($handle)) { if ($file == '.' || $file == '..') continue; if (substr($file, -4) != '.css') continue; $list[$file] = substr($file, 0, strlen($file) - 4); } closedir($handle); } $dir = WP_CONTENT_DIR . '/extensions/newsletter/' . $this->module . '/styles'; if (is_dir($dir)) { $handle = @opendir($dir); if ($handle !== false) { while ($file = readdir($handle)) { if ($file == '.' || $file == '..') continue; if (isset($list[$file])) continue; if (substr($file, -4) != '.css') continue; $list[$file] = substr($file, 0, strlen($file) - 4); } closedir($handle); } } return $list; } function get_style_url($style) { if (is_file(WP_CONTENT_DIR . '/extensions/newsletter/' . $this->module . '/styles/' . $style)) return WP_CONTENT_URL . '/extensions/newsletter/' . $this->module . '/styles/' . $style; else return plugins_url('newsletter') . '/' . $this->module . '/styles/' . $style; } function admin_menu() { } function add_menu_page($page, $title, $capability = '') { if (!Newsletter::instance()->is_allowed()) return; $name = 'newsletter_' . $this->module . '_' . $page; add_submenu_page('newsletter_main_index', $title, $title, 'exist', $name, array($this, 'menu_page')); } function add_admin_page($page, $title) { if (!Newsletter::instance()->is_allowed()) return; $name = 'newsletter_' . $this->module . '_' . $page; $name = apply_filters('newsletter_admin_page', $name); add_submenu_page(null, $title, $title, 'exist', $name, array($this, 'menu_page')); } function sanitize_file_name($name) { return preg_replace('/[^a-z_\\-]/i', '', $name); } function menu_page() { global $plugin_page, $newsletter, $wpdb; $parts = explode('_', $plugin_page, 3); $module = $this->sanitize_file_name($parts[1]); $page = $this->sanitize_file_name($parts[2]); $page = str_replace('_', '-', $page); $file = NEWSLETTER_DIR . '/' . $module . '/' . $page . '.php'; require $file; } function get_admin_page_url($page) { return admin_url('admin.php') . '?page=newsletter_' . $this->module . '_' . $page; } /** Returns all the emails of the give type (message, feed, followup, ...) and in the given format * (default as objects). Return false on error or at least an empty array. Errors should never * occur. * * @global wpdb $wpdb * @param string $type * @return boolean|array */ function get_emails($type = null, $format = OBJECT) { global $wpdb; if ($type == null) { $list = $wpdb->get_results("select * from " . NEWSLETTER_EMAILS_TABLE . " order by id desc", $format); } else { $type = (string) $type; $list = $wpdb->get_results($wpdb->prepare("select * from " . NEWSLETTER_EMAILS_TABLE . " where type=%s order by id desc", $type), $format); } if ($wpdb->last_error) { $this->logger->error($wpdb->last_error); return false; } if (empty($list)) { return array(); } return $list; } /** * Retrieves an email from DB and unserialize the options. * * @param mixed $id * @param string $format */ function get_email($id, $format = OBJECT) { $email = $this->store->get_single(NEWSLETTER_EMAILS_TABLE, $id, $format); if (!$email) { return null; } if ($format == OBJECT) { $email->options = maybe_unserialize($email->options); if (!is_array($email->options)) { $email->options = array(); } if (empty($email->query)) { $email->query = "select * from " . NEWSLETTER_USERS_TABLE . " where status='C'"; } } else if ($format == ARRAY_A) { $email['options'] = maybe_unserialize($email['options']); if (!is_array($email['options'])) { $email['options'] = array(); } if (empty($email['query'])) { $email['query'] = "select * from " . NEWSLETTER_USERS_TABLE . " where status='C'"; } } return $email; } /** * Save an email and provide serialization, if needed, of $email['options']. */ function save_email($email, $return_format = OBJECT) { if (is_object($email)) { $email = (array) $email; } if (isset($email['subject'])) { if (mb_strlen($email['subject'], 'UTF-8') > 250) { $email['subject'] = mb_substr($email['subject'], 0, 250, 'UTF-8'); } } if (isset($email['options']) && is_array($email['options'])) { $email['options'] = serialize($email['options']); } $email = $this->store->save(NEWSLETTER_EMAILS_TABLE, $email, $return_format); if ($return_format == OBJECT) { $email->options = maybe_unserialize($email->options); if (!is_array($email->options)) $email->options = array(); } else if ($return_format == ARRAY_A) { $email['options'] = maybe_unserialize($email['options']); if (!is_array($email['options'])) $email['options'] = array(); } return $email; } function get_email_from_request() { if (isset($_REQUEST['nek'])) { list($id, $token) = @explode('-', $_REQUEST['nek'], 2); } else { return null; } $email = $this->get_email($id); return $email; } /** * * @global wpdb $wpdb * @param int|array $id * @return boolean */ function delete_email($id) { global $wpdb; $r = $this->store->delete(NEWSLETTER_EMAILS_TABLE, $id); if ($r !== false) { // $id could be an array if IDs $id = (array) $id; foreach ($id as $email_id) { $wpdb->delete(NEWSLETTER_STATS_TABLE, array('email_id' => $email_id)); $wpdb->delete(NEWSLETTER_SENT_TABLE, array('email_id' => $email_id)); } } return $r; } function get_email_field($id, $field_name) { return $this->store->get_field(NEWSLETTER_EMAILS_TABLE, $id, $field_name); } function get_email_status_slug($email) { $email = (object) $email; if ($email->status == 'sending' && $email->send_on > time()) { return 'scheduled'; } return $email->status; } function get_email_status_label($email) { $email = (object) $email; $status = $this->get_email_status_slug($email); switch ($status) { case 'sending': return __('Sending', 'newsletter'); case 'scheduled': return __('Scheduled', 'newsletter'); case 'sent': return __('Sent', 'newsletter'); case 'paused': return __('Paused', 'newsletter'); case 'new': return __('Draft', 'newsletter'); default: return ucfirst($email->status); } } function show_email_status_label($email) { echo '', esc_html($this->get_email_status_label($email)), ''; } function get_email_progress($email, $format = 'percent') { return $email->total > 0 ? intval($email->sent / $email->total * 100) : 0; } function show_email_progress_bar($email, $attrs = array()) { $email = (object) $email; $attrs = array_merge(array('format' => 'percent', 'numbers' => false, 'scheduled' => false), $attrs); if ($email->status == 'sending' && $email->send_on > time()) { if ($attrs['scheduled']) { echo '', $this->format_date($email->send_on), ''; } } else if ($email->status == 'new') { echo ''; } else { $percent = $this->get_email_progress($email); $label = $percent; if ($attrs['format'] == 'numbers') { $label = $email->sent . ' ' . __('of', 'newsletter') . ' ' . $email->total; } echo '' . wp_trim_words($excerpt, $words) . '
'; }