<?php namespace Resmush\Notices; class NoticeModel //extends ShortPixelModel { public $message; // The message we want to convey. public $details = array(); // extra details, like the files involved. Something could be hideable in the future. public $code; private $id = null; // used for persistent messages. protected $viewed = false; // was this notice viewed? protected $is_persistent = false; // This is a fatal issue, display until something was fixed. protected $is_dismissed = false; // for persistent notices, protected $suppress_until = null; protected $suppress_period = -1; protected $include_screens = array(); protected $exclude_screens = array(); public $is_removable = true; // if removable, display a notice dialog with red X or so. public $messageType = self::NOTICE_NORMAL; public $notice_action; // empty unless for display. Ajax action to talk back to controller. protected $callback; // empty unless callback is needed public static $icons = array(); private static $jsDismissLoaded; const NOTICE_NORMAL = 1; const NOTICE_ERROR = 2; const NOTICE_SUCCESS = 3; const NOTICE_WARNING = 4; /** Use this model in conjunction with NoticeController, do not call directly */ public function __construct($message, $messageType = self::NOTICE_NORMAL) { $this->message = $message; $this->messageType = $messageType; } public function isDone() { // check suppressed if ($this->is_dismissed && ! is_null($this->suppress_until)) { if (time() >= $this->suppress_until) { $this->is_persistent = false; // unpersist, so it will be cleaned and dropped. } } if ($this->viewed && ! $this->is_persistent) return true; else return false; } public function getID() { return $this->id; } public function isPersistent() { return $this->is_persistent; } public function isDismissed() { return $this->is_dismissed; } public function dismiss() { $this->is_dismissed = true; $this->suppress_until = time() + $this->suppress_period; } public function unDismiss() { $this->is_dismissed = false; } public function setDismissedUntil($timestamp) { $this->suppress_until = $timestamp; } /** Support for extra information beyond the message. * Can help to not overwhelm users w/ the same message but different file /circumstances. */ public function addDetail($detail, $clean = false) { if ($clean) $this->details = array(); if (! in_array($detail, $this->details) ) $this->details[] = $detail; } /** * @param $method String Include or Exclude * @param $includes String|Array Screen Names to Include / Exclude either string, or array */ public function limitScreens($method, $screens) { if ($method == 'exclude') { $var = 'exclude_screens'; } else { $var = 'include_screens'; } if (is_array($screens)) { $this->$var = array_merge($this->$var, $screens); } else { $this->{$var}[] = $screens; // strange syntax is PHP 5.6 compat. } } /* Checks if Notice is allowed on this screen * @param @screen_id String The screen Id to check ( most likely current one, via EnvironmentModel) */ public function checkScreen($screen_id) { if (in_array($screen_id, $this->exclude_screens)) { return false; } if (in_array($screen_id, $this->include_screens)) { return true; } // if include is set, don't show if not screen included. if (count($this->include_screens) == 0) { return true; } else { return false; } } /** Set a notice persistent. Meaning it shows every page load until dismissed. * @param $key Unique Key of this message. Required * @param $suppress When dismissed do not show this message again for X amount of time. When -1 it will just be dropped from the Notices and not suppressed */ public function setPersistent($key, $suppress = -1, $callback = null) { $this->id = $key; $this->is_persistent = true; $this->suppress_period = $suppress; if ( ! is_null($callback) && is_callable($callback)) { $this->callback = $callback; } } public static function setIcon($notice_type, $icon) { switch($notice_type) { case 'error': $type = self::NOTICE_ERROR; break; case 'success': $type = self::NOTICE_SUCCESS; break; case 'warning': $type = self::NOTICE_WARNING; break; case 'normal': default: $type = self::NOTICE_NORMAL; break; } self::$icons[$type] = $icon; } public function _debug_getvar($var) { if (property_exists($this, $var)) { return $this->$var; } } private function checkIncomplete($var) { return ($var instanceof \__PHP_Incomplete_Class); } public function getForDisplay() { $this->viewed = true; $class = 'shortpixel shortpixel-notice '; $icon = ''; if ($this->callback) { if (is_array($this->callback)) { foreach($this->callback as $part) { if ($this->checkIncomplete($part) === true) { return false; } } } elseif (is_object($this->callback)) { if ($this->checkIncomplete($part) === true) return false; } if (! is_callable($this->callback)) { return; } else { $return = call_user_func($this->callback, $this); if ($return === false) // don't display is callback returns false explicitly. return; } } switch($this->messageType) { case self::NOTICE_ERROR: $class .= 'notice-error '; $icon = isset(self::$icons[self::NOTICE_ERROR]) ? self::$icons[self::NOTICE_ERROR] : ''; //$icon = 'scared'; break; case self::NOTICE_SUCCESS: $class .= 'notice-success '; $icon = isset(self::$icons[self::NOTICE_SUCCESS]) ? self::$icons[self::NOTICE_SUCCESS] : ''; break; case self::NOTICE_WARNING: $class .= 'notice-warning '; $icon = isset(self::$icons[self::NOTICE_WARNING]) ? self::$icons[self::NOTICE_WARNING] : ''; break; case self::NOTICE_NORMAL: $class .= 'notice-info '; $icon = isset(self::$icons[self::NOTICE_NORMAL]) ? self::$icons[self::NOTICE_NORMAL] : ''; break; default: $class .= 'notice-info '; $icon = ''; break; } if ($this->is_removable) { $class .= 'is-dismissible '; } if ($this->is_persistent) { $class .= 'is-persistent '; } $id = ! is_null($this->id) ? $this->id : uniqid(); //'id="' . $this->id . '"' $output = "<div id='$id' class='$class'><span class='icon'> " . $icon . "</span> <span class='content'>" . $this->message; if ($this->hasDetails()) { $output .= '<div class="details-wrapper"> <input type="checkbox" name="detailhider" id="check-' . $id .'"> <label for="check-' . $id . '" class="show-details"><span>' . __('See Details', 'resmushit-image-optimizer/') . '</span> </label>'; $output .= "<div class='detail-content-wrapper'><p class='detail-content'>" . $this->parseDetails() . "</p></div>"; $output .= '<label for="check-' . $id . '" class="hide-details"><span>' . __('Hide Details', 'resmushit-image-optimizer/') . '</span></label>'; $output .= '</div>'; // detail wrapper } $output .= "</span>"; if ($this->is_removable) { $output .= '<button type="button" id="button-' . $id . '" class="notice-dismiss" data-dismiss="' . $this->suppress_period . '" ><span class="screen-reader-text">' . __('Dismiss this notice', 'resmushit-image-optimizer/') . '</span></button>'; if (! $this->is_persistent) { $output .= "<script type='text/javascript'>\n document.getElementById('button-$id').onclick = function() { var el = document.getElementById('$id'); jQuery(el).fadeTo(100,0,function() { jQuery(el).slideUp(100, 0, function () { jQuery(el).remove(); }) }); } </script>"; } } $output .= "</div>"; if ($this->is_persistent && $this->is_removable) { $output .= "<script type='text/javascript'>\n" . $this->getDismissJS() . "\n</script>"; } return $output; } protected function hasDetails() { if (is_array($this->details) && count($this->details) > 0) return true; else return false; } protected function parseDetails() { return implode('<BR>', $this->details); } private function getDismissJS() { $js = ''; if (is_null(self::$jsDismissLoaded)) { $nonce = wp_create_nonce('dismiss'); $url = wp_json_encode(admin_url('admin-ajax.php')); $js = "function shortpixel_notice_dismiss(event) { event.preventDefault(); var ev = event.detail; var target = event.target; var parent = target.parentElement; var data = { 'plugin_action': 'dismiss', 'action' : '$this->notice_action', 'nonce' : '$nonce', } data.time = target.getAttribute('data-dismiss'); data.id = parent.getAttribute('id'); jQuery.post($url,data); jQuery(parent).fadeTo(100,0,function() { jQuery(parent).slideUp(100, 0, function () { jQuery(parent).remove(); }) }); }"; } $js .= ' jQuery("#' . $this->id . '").find(".notice-dismiss").on("click", shortpixel_notice_dismiss); '; return "\n jQuery(document).ready(function(){ \n" . $js . "\n});"; } }