/**
  * Register a license for status checks.
  *
  * @access public
  * @since  8.5.28
  *
  * @param string $file The full path and filename of the file.
  * @param array  $data {
  *     @type int    $item_id   The plugin ID.
  *                             Optional if $item_name provided otherwise it is required.
  *     @type string $item_name The plugin name exactly as in the store.
  *                             Optional if the $item_id is provided otherwise it is required.
  *     @type string $author    The plugin author name.
  *     @type string $version   The current plugin version; not, the latest version.
  *                             Required.
  *     @type string $license   The license key. Optional.
  * }
  *
  * @return bool|WP_Error  TRUE on success, WP_Error on failure.
  */
 public static function register($file, array $data)
 {
     $defaults = array('item_id' => 0, 'item_name' => '', 'author' => '', 'version' => '', 'license' => '');
     $plugin = cnSanitize::args($data, $defaults);
     if (empty($plugin['item_name']) && empty($plugin['item_id'])) {
         return new WP_Error('plugin_id_or_name_not_provided', esc_html__('Plugin name or ID is required.', 'connections'), $plugin);
     }
     if (empty($plugin['version'])) {
         return new WP_Error('plugin_version_not_provided', esc_html__('Plugin version is required.', 'connections'), $plugin);
     }
     //$plugin['file']     = $file;
     $plugin['basename'] = plugin_basename($file);
     //$plugin['slug']     = basename( $file, '.php' );
     $plugin['slug'] = self::get_slug($plugin['item_name']);
     $plugin['item_id'] = absint($plugin['item_id']);
     self::$licenses[$plugin['basename']] = $plugin;
     return TRUE;
 }
Example #2
0
 /**
  * Tints the image a different color
  *
  * @access public
  * @since  8.1
  *
  * @param string $hexColor color e.g. #ff00ff
  * @return boolean|WP_Error
  */
 public function colorize($hexColor)
 {
     $hexColor = cnSanitize::hexColor($hexColor);
     if (empty($hexColor)) {
         return new WP_Error('image_colorize_error', __('Value passed to ' . get_class($this) . '::colorize() is an invalid hex color.', 'connections'), $this->file);
     }
     if (function_exists('imagefilter') && function_exists('imagesavealpha') && function_exists('imagealphablending')) {
         $hexColor = preg_replace('#^\\##', '', $hexColor);
         $r = hexdec(substr($hexColor, 0, 2));
         $g = hexdec(substr($hexColor, 2, 2));
         $b = hexdec(substr($hexColor, 2, 2));
         imagealphablending($this->image, FALSE);
         if (imagefilter($this->image, IMG_FILTER_COLORIZE, $r, $g, $b, 0)) {
             imagesavealpha($this->image, TRUE);
             return TRUE;
         }
     }
     return new WP_Error('image_colorize_error', __('Image color change failed.', 'connections'), $this->file);
 }
 /**
  * @access public
  * @since  8.5.15
  *
  * @global wpdb $wpdb
  *
  * @param array  $atts
  *
  * @return string
  */
 public static function where($atts = array())
 {
     global $wpdb;
     $defaults = array('table' => CN_ENTRY_TABLE, 'field' => '', 'value' => '', 'format' => '%s', 'relation' => 'AND', 'delimiter' => '|');
     $atts = cnSanitize::args($atts, $defaults);
     $where = '';
     $atts['relation'] = in_array($atts['relation'], array('AND', 'OR')) ? strtoupper($atts['relation']) : 'AND';
     if (0 < strlen($atts['field']) && 0 < count($atts['value'])) {
         $value = cnFunction::parseStringList($atts['value'], $atts['delimiter']);
         $count = count($value);
         if (1 < $count) {
             $where = $atts['relation'] . ' ' . $atts['table'] . '.' . $atts['field'] . ' ' . self::in($value, $atts['format']);
         } elseif (1 == $count) {
             $where = $wpdb->prepare($atts['relation'] . ' ' . $atts['table'] . '.' . $atts['field'] . ' = ' . $atts['format'], $value);
         }
     }
     return $where;
 }
 /**
  * The string to set the <a> or <img> alt attribute.
  *
  * @access public
  * @since  8.2.5
  *
  * @param string $alt
  */
 public function setAlt($alt)
 {
     $this->alt = is_string($alt) && 0 < strlen($alt) ? cnSanitize::field('attribute', $alt) : '';
 }
 /**
  * Returns an indexed array of objects the addresses per the defined options.
  *
  * @param $atts {
  *     @type string       $fields    The fields to return.
  *                                   Default: all
  *                                   Accepts: all, ids, locality, regions, postal-code, country
  *     @type int          $id        The entry ID in which to retrieve the addresses for.
  *     @type bool         $preferred Whether or not to return only the preferred address.
  *                                   Default: false
  *     @type array|string $type      The address types to return.
  *                                   Default: array() which will return all registered address types.
  *                                   Accepts: home, work, school, other and any other registered types.
  *     @type array|string $city      Return address in the defined cities.
  *     @type array|string $state     Return address in the defined states.
  *     @type array|string $country   Return address in the defined countries.
  *     @type array        $coordinates {
  *         Return the addresses at the specific coordinates.
  *         @type float $latitude
  *         @type float $longitude
  *     }
  * }
  *
  * @return array
  */
 public function addresses($atts = array())
 {
     /** @var wpdb $wpdb */
     global $wpdb;
     $where = array('WHERE 1=1');
     /*
      * // START -- Set the default attributes array. \\
      */
     $defaults = array('fields' => 'all', 'id' => NULL, 'preferred' => FALSE, 'type' => array(), 'city' => array(), 'state' => array(), 'zipcode' => array(), 'country' => array(), 'coordinates' => array(), 'limit' => NULL);
     $atts = cnSanitize::args($atts, $defaults);
     /*
      * // END -- Set the default attributes array if not supplied. \\
      */
     /**
      * @var int          $id
      * @var bool         $preferred
      * @var array|string $type
      * @var array|string $city
      * @var array|string $state
      * @var array|string $zipcode
      * @var array|string $country
      * @var array        $coordinates
      * @var null|int     $limit
      */
     extract($atts);
     /*
      * Convert these to values to an array if they were supplied as a comma delimited string
      */
     /** @var array $type */
     cnFunction::parseStringList($type);
     /** @var array $city */
     cnFunction::parseStringList($city);
     /** @var array $state */
     cnFunction::parseStringList($state);
     /** @var array $zipcode */
     cnFunction::parseStringList($zipcode);
     /** @var array $country */
     cnFunction::parseStringList($country);
     switch ($atts['fields']) {
         case 'ids':
             $select = array('a.id', 'a.entry_id');
             break;
         case 'locality':
             $select = array('a.city');
             break;
         case 'region':
             $select = array('a.state');
             break;
         case 'postal-code':
             $select = array('a.zipcode');
             break;
         case 'country':
             $select = array('a.country');
             break;
         default:
             $select = array('a.*');
     }
     if (!empty($id)) {
         $where[] = $wpdb->prepare('AND `entry_id` = %d', $id);
     }
     if (!empty($preferred)) {
         $where[] = $wpdb->prepare('AND `preferred` = %d', (bool) $preferred);
     }
     if (!empty($type)) {
         $where[] = $wpdb->prepare('AND `type` IN (' . cnFormatting::prepareINPlaceholders($type) . ')', $type);
     }
     if (!empty($city)) {
         $where[] = $wpdb->prepare('AND `city` IN (' . cnFormatting::prepareINPlaceholders($city) . ')', $city);
     }
     if (!empty($state)) {
         $where[] = $wpdb->prepare('AND `state` IN (' . cnFormatting::prepareINPlaceholders($state) . ')', $state);
     }
     if (!empty($zipcode)) {
         $where[] = $wpdb->prepare('AND `zipcode` IN (' . cnFormatting::prepareINPlaceholders($zipcode) . ')', $zipcode);
     }
     if (!empty($country)) {
         $where[] = $wpdb->prepare('AND `country` IN (' . cnFormatting::prepareINPlaceholders($country) . ')', $country);
     }
     if (!empty($coordinates)) {
         if (!empty($coordinates['latitude']) && !empty($coordinates['longitude'])) {
             $where[] = $wpdb->prepare('AND `latitude` = %f', $coordinates['latitude']);
             $where[] = $wpdb->prepare('AND `longitude` = %f', $coordinates['longitude']);
         }
     }
     // Limit the characters that are queried based on if the current user can view public, private or unlisted entries.
     $where = self::setQueryVisibility($where, array('table' => 'a'));
     $limit = is_null($atts['limit']) ? '' : sprintf(' LIMIT %d', $atts['limit']);
     $sql = sprintf('SELECT %1$s FROM %2$s AS a %3$s ORDER BY `order`%4$s', implode(', ', $select), CN_ENTRY_ADDRESS_TABLE, implode(' ', $where), $limit);
     $results = $wpdb->get_results($sql);
     return $results;
 }
Example #6
0
 /**
  * Uses WP's Image Editor Class to crop and resize images.
  *
  * Derived from bfithumb.
  * @link https://github.com/bfintal/bfi_thumb
  * Incorporated crop only from Github pull request 13
  * @link https://github.com/bfintal/bfi_thumb/pull/13
  * Also incorporates positional cropping and image quality change from the Dominic Whittle bfithumb fork:
  * @link https://github.com/dominicwhittle/bfi_thumb
  * Crop mode support was inspired by TimThumb.
  * @link http://www.binarymoon.co.uk/projects/timthumb/
  *
  * bfiThumb was inspired by Aqua Resizer
  * @url https://github.com/syamilmj/Aqua-Resizer
  *
  * @todo  Should an option be added to control the order filters should be applied be added? Filter order can affect result...
  *
  * Accepted option for the $atts property are:
  * 	width (int|string) Width in pixels or percentage. If using percentage, the percentage symbol must be included, example `50%`.
  * 	height (int|string) Height in pixels or percentage. If using percentage, the percentage symbol must be included, example `50%`.
  *
  * 	negate (bool) Whether or not to apply the negate filter. Default: FALSE
  * 	grayscale (bool) Whether or not to apply the grayscale filter. Default: FALSE
  * 	brightness (int) Adjust the image brightness. Valid range is -255–255 (-255 = min brightness, 0 = no change, +255 = max brightness). Default: 0
  * 	colorize (string) Colorize the image. Either a valid hex-color #000000–#ffffff or a HTML named color like `red` can be supplied. Default: NULL
  * 		@see  cnColor::$colors for a list of valid named colors.
  * 	contrast (int) Ajust the image contrast. Valid range is -100–100 (-100 = max contrast, 0 = no change, +100 = min contrast [note the direction]) Default: 0
  * 	detect_edges (bool) Whether of not to apply the detect edges filter. Default: FALSE
  * 	emboss (bool) Whether or not to apply the emboss filter. Default: FALSE
  * 	gassian_blur (bool) Whether of not to apply a gaussian blur. Default: FALSE
  * 	blur (bool) Whether or not to apply the blur filter. Default: FALSE
  * 	sketchy (bool) Whether or not to apply the the skethy filter. Default: FALSE
  * 	sharpen (bool) Whether or not to apply the sharpen filter. Default: FALSE
  * 	smooth (int) Apply the smooth filter. Valid range is -100–100 (-100 = max smooth, 100 = min smooth). Default: NULL
  * 	opacity (int) Set the image opacity. Valid range is 0–100 (0 = fully transparent, 100 = fully opaque). Default: 100
  *
  * 	crop_mode (int) Which crop mode to utilize when rescaling the image. Valid range is 0–3. Default: 1
  * 		0 == Resize to Fit specified dimensions with no cropping. Aspect ratio will not be maintained.
  * 		1 == Crop and resize to best fit dimensions maintaining aspect ration. Default.
  * 		2 == Resize proportionally to fit entire image into specified dimensions, and add margins if required.
  * 			Use the canvas_color option to set the color to be used when adding margins.
  * 		3 == Resize proportionally adjusting size of scaled image so there are no margins added.
  * 	crop_focus (array|string) The crop focus/positional cropping is used to determine the center origin of a crop when crop_mode is set 1.
  * 		Valid range is (float) 0.0–1.0
  * 		Default: array( .5, .5)
  * 		Text options are also supported:
  * 			'left,top' | array( 'left', 'top' ) == array( 0, 0 )
  * 			'center,top' | array( 'center', 'top' ) == array( .5, 0 )
  * 			'right,top' | array( 'right', 'top' ) == array( 1, 0 )
  * 			'left,center' | array( 'left', 'center' )  == array( 0, .5 )
  * 			'center,center' | array( 'center', 'center' ) == array( .5, .5) [the default crop focus].
  * 			'right,center' | array( 'right', 'center' ) == array( 1, .5 )
  * 			'left,bottom' | array( 'left', 'bottom' ) == array( 0, 1 )
  * 			'center,bottom' | array( 'center', 'bottom' ) == array( .5, 1 )
  * 			'right,bottom' | array( 'right', 'bottom' ) == array( 1, 1 )
  *
  * 	crop_only (bool) Whether or not to just crop the image.
  * 		If set to TRUE, crop_x, crop_y, crop_width, crop_height must be supplied.
  * 		This overrides crop_mode.
  * 		Default: FALSE
  * 	crop_x (int|string) The x-axis crop origin start in pixels or percentage. If using percentage, the percentage symbol must be included, example `50%`.
  * 	crop_y (int|string) The y-axis crop origin start in pixels or percentage. If using percentage, the percentage symbol must be included, example `50%`.
  * 	crop_width (int|string) The resize width of the crop in pixels or percentage. If using percentage, the percentage symbol must be included, example `50%`.
  * 		The width option can be set to determine the final scaled width.
  * 	crop_height (int|string) The resize height of the crop in pixels or percentage. If using percentage, the percentage symbol must be included, example `50%`.
  * 		The height option can be set to determine the final scaled height.
  *
  * 	canvas_color (string) Either a valid hex-color #000000–#ffffff or a HTML named color like `red` can be supplied or set to 'transparent'.
  * 		The canvas_color is only used when using crop_mode=2. This will be the color of the margins.
  * 		Default: #FFFFFF
  * 		@see  cnColor::$colors for a list of valid named colors.
  *
  * 	quality (int) The image quality to be used when saving the image. Valid range is 1–100. Default: 90
  *
  * @param  string $source The local image path or URL to process. The image must be in the upload folder or the theme folder.
  * @param  array  $atts   An associative array containing the options used to process the image.
  * @param  string $return
  *
  * @return mixed  array | object | string | stream
  *                If $return is `base64` then base64 encoded image data URI will be returned. Suitable for use in CSS or img src attribute.
  *                If $return is `data` and array of the image meta is returned.
  *                If $return is `editor` an instance if the WP_Image_Editor is returned.
  *                If $return is `stream` the image resource will be streamed to the browser with the correct headers set.
  *                If $return is `url` the image URL will be returned. [Default]
  */
 public static function get($source, $atts = array(), $return = 'url')
 {
     global $wp_filter;
     // Increase PHP script execution by 60. This should help on hosts
     // that permit this change from page load timeouts from occurring
     // due to large number of images that might have to be created and cached.
     @set_time_limit(60);
     // Set artificially high because GD uses uncompressed images in memory.
     // Even though Imagick uses less PHP memory than GD, set higher limit for users that have low PHP.ini limits.
     @ini_set('memory_limit', apply_filters('image_memory_limit', WP_MAX_MEMORY_LIMIT));
     $filter = array();
     $methods = array();
     $log = new cnLog_Stateless();
     /*
      * Temporarily store the filters hooked to the image editor filters.
      */
     $filter['editors'] = isset($wp_filter['wp_image_editors']) ? $wp_filter['wp_image_editors'] : '';
     $filter['resize'] = isset($wp_filter['image_resize_dimensions']) ? $wp_filter['image_resize_dimensions'] : '';
     /*
      * Remove all filters hooked into the the image editor filters to prevent conflicts.
      */
     remove_all_filters('wp_image_editors');
     remove_all_filters('image_resize_dimensions');
     /*
      * Start an instance of the logger if WP_DEBUG is defind and TRUE.
      */
     $log->add('image_process_start', __('Image processing started.', 'connections'));
     /*
      * Use the cnImage editors.
      */
     add_filter('wp_image_editors', array(__CLASS__, 'imageEditors'));
     /*
      * Do not use the default resizer since we want to allow resizing to larger sizes than the original image.
      * Parts are borrowed from media.php file in WordPress core.
      */
     add_filter('image_resize_dimensions', array(__CLASS__, 'resize_dimensions'), 10, 6);
     $defaults = array('width' => 0, 'height' => 0, 'negate' => FALSE, 'grayscale' => FALSE, 'brightness' => 0, 'colorize' => NULL, 'contrast' => 0, 'detect_edges' => FALSE, 'emboss' => FALSE, 'gaussian_blur' => FALSE, 'blur' => FALSE, 'sketchy' => FALSE, 'sharpen' => FALSE, 'smooth' => NULL, 'opacity' => 100, 'crop_mode' => 1, 'crop_focus' => array(0.5, 0.5), 'crop_only' => FALSE, 'canvas_color' => '#FFFFFF', 'quality' => 90, 'sub_dir' => '');
     $atts = wp_parse_args(apply_filters('cn_get_image_atts', $atts, $source, $return), $defaults);
     do_action('cn_image_get', $atts, $source, $return);
     /**
      * @var $width
      * @var $height
      * @var $negate
      * @var $grayscale
      * @var $brightness
      * @var $colorize
      * @var $contrast
      * @var $detect_edges
      * @var $emboss
      * @var $gaussian_blur
      * @var $blur
      * @var $sketchy
      * @var $sharpen
      * @var $smooth
      * @var $opacity
      * @var $crop_mode
      * @var $crop_focus
      * @var $crop_only
      * @var $canvas_color
      * @var $quality
      * @var $sub_dir
      */
     extract($atts);
     /*
      * --> START <-- Sanitize/Validate $atts values.
      */
     if (path_is_absolute($source)) {
         $log->add('image_path', __(sprintf('Supplied Source Path: %s', $source), 'connections'));
     } else {
         $source = esc_url($source);
         $log->add('image_url', __(sprintf('Supplied Source URL: %s', $source), 'connections'));
     }
     if (empty($source)) {
         return new WP_Error('no_path_or_url_provided', __('No image path or URL supplied.', 'connections'), $source);
     }
     if (!is_bool($negate)) {
         $negate = FALSE;
     }
     if (!is_bool($grayscale)) {
         $grayscale = FALSE;
     }
     if (!is_numeric($brightness) || empty($brightness)) {
         unset($brightness);
     }
     if (!is_numeric($contrast) || empty($contrast)) {
         unset($contrast);
     }
     if (!is_null($colorize)) {
         // If $colorize is a HEX color, ensure it is hashed.
         $colorize = cnFormatting::maybeHashHEXColor($colorize);
         // Check to see if $colorize is a valid HEX color.
         if (!cnSanitize::hexColor($colorize)) {
             // Since $colorize is not a valid HEX color, check to see if it is a named color.
             $colorize = cnColor::name2hex($colorize);
             // If $colorize is not a named color, unset it.
             if ($colorize === FALSE) {
                 unset($colorize);
             }
         }
     } else {
         unset($colorize);
     }
     if (!is_bool($detect_edges)) {
         $detect_edges = FALSE;
     }
     if (!is_bool($emboss)) {
         $emboss = FALSE;
     }
     if (!is_bool($gaussian_blur)) {
         $gaussian_blur = FALSE;
     }
     if (!is_bool($blur)) {
         $blur = FALSE;
     }
     if (!is_bool($sketchy)) {
         $sketchy = FALSE;
     }
     if (!is_bool($sharpen)) {
         $sharpen = FALSE;
     }
     if (!is_numeric($smooth) || is_null($smooth)) {
         unset($smooth);
     }
     // Ensure valid value for opacity.
     if (!is_numeric($opacity)) {
         $opacity = 100;
     }
     // Ensure valid value for crop mode.
     if (filter_var((int) $crop_mode, FILTER_VALIDATE_INT, array('options' => array('min_range' => 0, 'max_range' => 3))) === FALSE) {
         $crop_mode = 1;
     }
     $log->add('image_crop_mode', __(sprintf('Crop Mode: %d', $crop_mode), 'connections'));
     // Crop can be defined as either an array or string, sanitized/validate both.
     if (is_array($crop_focus) || is_string($crop_focus)) {
         // If $crop_focus is a string, lets check if is a positional crop and convert to an array.
         if (is_string($crop_focus) && stripos($crop_focus, ',') !== FALSE) {
             $crop_focus = explode(',', $crop_focus);
             array_walk($crop_focus, 'trim');
         }
         // Convert the string values to their float equivalents.
         if (is_string($crop_focus[0])) {
             switch ($crop_focus[0]) {
                 case 'left':
                     $crop_focus[0] = 0;
                     break;
                 case 'right':
                     $crop_focus[0] = 1;
                     break;
                 default:
                     $crop_focus[0] = 0.5;
                     break;
             }
         }
         if (is_string($crop_focus[1])) {
             switch ($crop_focus[1]) {
                 case 'top':
                     $crop_focus[1] = 0;
                     break;
                 case 'bottom':
                     $crop_focus[1] = 1;
                     break;
                 default:
                     $crop_focus[1] = 0.5;
                     break;
             }
         }
         // Ensure if an array was supplied, that there are only two keys, if not, set the default positional crop.
         if (count($crop_focus) !== 2) {
             $crop_focus = array(0.5, 0.5);
             // Values must be a float within the range of 0–1, if is not, set the default positional crop.
         } else {
             if ((!$crop_focus[0] >= 0 || !$crop_focus <= 1) && filter_var((double) $crop_focus[0], FILTER_VALIDATE_FLOAT) === FALSE) {
                 $crop_focus[0] = 0.5;
             }
             if ((!$crop_focus[1] >= 0 || !$crop_focus <= 1) && filter_var((double) $crop_focus[1], FILTER_VALIDATE_FLOAT) === FALSE) {
                 $crop_focus[1] = 0.5;
             }
         }
         $log->add('image_crop_focus', 'Crop Focus: ' . implode(',', $crop_focus));
     } else {
         // If $crop_focus is not an array, it must be a (bool) FALSE and if it is not, set $crop_focus to FALSE.
         $crop_focus = FALSE;
     }
     if (!is_bool($crop_only)) {
         $crop_only = FALSE;
     }
     // If $canvas_color is a HEX color, ensure it is hashed.
     $canvas_color = cnFormatting::maybeHashHEXColor($canvas_color);
     // Check to see if $canvas_color is a valid HEX color.
     if (!cnSanitize::hexColor($canvas_color)) {
         // Check to see if it is `transparent`, if not, check if it is a named color.
         if (strtolower($canvas_color) === 'transparent') {
             $canvas_color = 'transparent';
         } else {
             // Check to see if it is a named color.
             $canvas_color = cnColor::name2hex($canvas_color);
             // Not a named color, set the default.
             if ($canvas_color === FALSE) {
                 $canvas_color = '#FFFFFF';
             }
         }
     }
     // Ensure valid value for $quality. If invalid valid is supplied reset to the default of 90, matching WP core.
     if (filter_var((int) $quality, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 100))) === FALSE) {
         $quality = 90;
     }
     /*
      * --> END <-- Sanitize/Validate $atts values.
      */
     // Define upload path & dir.
     $upload_dir = CN_IMAGE_PATH;
     $upload_url = CN_IMAGE_BASE_URL;
     // Get image info or return WP_Error.
     if (is_wp_error($image_info = self::info($source))) {
         return $image_info;
     }
     $log->add('image_path', __(sprintf('Verified Source Path: %s', $image_info['path']), 'connections'));
     // This is the filename.
     $basename = $image_info['basename'];
     $log->add('image_base_filename', 'Original filename: ' . $basename);
     // Path/File info.
     $ext = $image_info['extension'];
     // Image info.
     $orig_w = $image_info[0];
     $orig_h = $image_info[1];
     $orig_mime_type = $image_info['mime'];
     $log->add('image_original_info', 'Original width: ' . $orig_w);
     $log->add('image_original_info', 'Original height: ' . $orig_h);
     $log->add('image_original_info', 'Original mime: ' . $orig_mime_type);
     // Support percentage dimensions. Compute percentage based on the original dimensions.
     if (is_string($width) && !is_numeric($width)) {
         if (stripos($width, '%') !== FALSE) {
             $log->add('image_width_percentage', 'Width set as percentage.');
             $width = (int) ((double) str_replace('%', '', $width) / 100 * $orig_w);
             $log->add('image_width', 'Width: ' . $width);
         }
     } else {
         $width = absint($width);
         $log->add('image_width', 'Width: ' . ($width === 0 ? '0' : $width));
     }
     if (is_string($height) && !is_numeric($height)) {
         if (stripos($height, '%') !== FALSE) {
             $log->add('image_height_percentage', 'Height set as percentage.');
             $height = (int) ((double) str_replace('%', '', $height) / 100 * $orig_h);
             $log->add('image_height', 'Height: ' . $height);
         }
     } else {
         $height = absint($height);
         $log->add('image_height', 'Height: ' . ($height === 0 ? '0' : $height));
     }
     // The only purpose of this is to determine the final width and height
     // without performing any actual image manipulation. This will be used
     // to check whether a resize was done previously.
     if ((!empty($width) || !empty($height)) && $crop_only === FALSE) {
         switch ($crop_mode) {
             case 0:
                 $dims = image_resize_dimensions($orig_w, $orig_h, empty($width) ? NULL : $width, empty($height) ? NULL : $height, FALSE);
                 $dst_w = $dims[4];
                 $dst_h = $dims[5];
                 break;
             case 1:
                 $dims = image_resize_dimensions($orig_w, $orig_h, empty($width) ? NULL : $width, empty($height) ? NULL : $height, is_array($crop_focus) ? $crop_focus : TRUE);
                 $dst_w = $dims[4];
                 $dst_h = $dims[5];
                 break;
             case 2:
                 $canvas_w = $width;
                 $canvas_h = $height;
                 // generate new w/h if not provided
                 if ($width && !$height) {
                     $height = floor($orig_h * ($width / $orig_w));
                     $canvas_h = $height;
                 } else {
                     if ($height && !$width) {
                         $width = floor($orig_w * ($height / $orig_h));
                         $canvas_w = $width;
                     }
                 }
                 $final_height = $orig_h * ($width / $orig_w);
                 if ($final_height > $height) {
                     $origin_x = $width / 2;
                     $width = $orig_w * ($height / $orig_h);
                     $origin_x = round($origin_x - $width / 2);
                 } else {
                     $origin_y = $height / 2;
                     $height = $final_height;
                     $origin_y = round($origin_y - $height / 2);
                 }
                 $dst_w = $canvas_w;
                 $dst_h = $canvas_h;
                 break;
             case 3:
                 // generate new w/h if not provided
                 if ($width && !$height) {
                     $height = floor($orig_h * ($width / $orig_w));
                 } else {
                     if ($height && !$width) {
                         $width = floor($orig_w * ($height / $orig_h));
                     }
                 }
                 $final_height = $orig_h * ($width / $orig_w);
                 if ($final_height > $height) {
                     $width = $orig_w * ($height / $orig_h);
                 } else {
                     $height = $final_height;
                 }
                 $dims = image_resize_dimensions($orig_w, $orig_h, empty($width) ? NULL : $width, empty($height) ? NULL : $height, FALSE);
                 $dst_w = $dims[4];
                 $dst_h = $dims[5];
                 break;
         }
         $log->add('image_resize_width', 'Resize width: ' . ($dst_w === 0 ? '0' : $dst_w));
         $log->add('image_resize_height', 'Resize height: ' . ($dst_h === 0 ? '0' : $dst_h));
         // Do not resize, only a crop in the image.
     } elseif ($crop_only === TRUE) {
         // get x position to start cropping
         $src_x = isset($crop_x) ? $crop_x : 0;
         // get y position to start cropping
         $src_y = isset($crop_y) ? $crop_y : 0;
         // width of the crop
         if (isset($crop_width)) {
             $src_w = $crop_width;
         } else {
             if (isset($width)) {
                 $src_w = $width;
             } else {
                 $src_w = $orig_w;
             }
         }
         // height of the crop
         if (isset($crop_height)) {
             $src_h = $crop_height;
         } else {
             if (isset($height)) {
                 $src_h = $height;
             } else {
                 $src_h = $orig_h;
             }
         }
         // set the width resize with the crop
         if (isset($crop_width) && isset($width)) {
             $dst_w = $width;
         } else {
             $dst_w = NULL;
         }
         // set the height resize with the crop
         if (isset($crop_height) && isset($height)) {
             $dst_h = $height;
         } else {
             $dst_h = NULL;
         }
         // allow percentages
         if (isset($dst_w)) {
             if (stripos($dst_w, '%') !== FALSE) {
                 $dst_w = (int) ((double) str_replace('%', '', $dst_w) / 100 * $orig_w);
             }
         }
         if (isset($dst_h)) {
             if (stripos($dst_h, '%') !== FALSE) {
                 $dst_h = (int) ((double) str_replace('%', '', $dst_h) / 100 * $orig_h);
             }
         }
         $dims = image_resize_dimensions($src_w, $src_h, $dst_w, $dst_h, FALSE);
         $dst_w = $dims[4];
         $dst_h = $dims[5];
         // Make the pos x and pos y work with percentages
         if (stripos($src_x, '%') !== FALSE) {
             $src_x = (int) ((double) str_replace('%', '', $width) / 100 * $orig_w);
         }
         if (stripos($src_y, '%') !== FALSE) {
             $src_y = (int) ((double) str_replace('%', '', $height) / 100 * $orig_h);
         }
         // allow center to position crop start
         if ($src_x === 'center') {
             $src_x = ($orig_w - $src_w) / 2;
         }
         if ($src_y === 'center') {
             $src_y = ($orig_h - $src_h) / 2;
         }
     }
     // Create the hash for the saved file.
     // This to check whether we need to create a new file or use an existing file.
     $hash = (string) $image_info['modified'] . (empty($width) ? str_pad((string) $width, 5, '0', STR_PAD_LEFT) : '00000') . (empty($height) ? str_pad((string) $height, 5, '0', STR_PAD_LEFT) : '00000') . ($negate ? '1' : '0') . ($grayscale ? '1' : '0') . (isset($brightness) ? str_pad((string) ((int) $brightness >= 0 ? '1' . (string) $brightness : str_replace('-', '0', (string) $brightness)), 4, '0', STR_PAD_LEFT) : '0000') . (isset($colorize) ? str_pad(preg_replace('#^\\##', '', $colorize), 8, '0', STR_PAD_LEFT) : '00000000') . (isset($contrast) ? str_pad((string) ((int) $contrast >= 0 ? '1' . (string) $contrast : str_replace('-', '0', (string) $contrast)), 4, '0', STR_PAD_LEFT) : '0000') . ($detect_edges ? '1' : '0') . ($emboss ? '1' : '0') . ($gaussian_blur ? '1' : '0') . ($blur ? '1' : '0') . ($sketchy ? '1' : '0') . ($sharpen ? '1' : '0') . (isset($smooth) ? str_pad((string) ((double) $smooth >= 0 ? '1' . (string) $smooth : str_replace('-', '0', (string) $smooth)), 4, '0', STR_PAD_LEFT) : '0000') . str_pad((string) $opacity, 3, '0', STR_PAD_LEFT) . ($crop_focus ? is_array($crop_focus) ? str_replace('.', '', join('', $crop_focus)) : '1' : '0') . $crop_mode . ($crop_only ? '1' : '0') . (isset($src_x) ? str_pad((string) $src_x, 5, '0', STR_PAD_LEFT) : '00000') . (isset($src_y) ? str_pad((string) $src_y, 5, '0', STR_PAD_LEFT) : '00000') . (isset($src_w) ? str_pad((string) $src_w, 5, '0', STR_PAD_LEFT) : '00000') . (isset($src_h) ? str_pad((string) $src_h, 5, '0', STR_PAD_LEFT) : '00000') . (isset($dst_w) ? str_pad((string) $dst_w, 5, '0', STR_PAD_LEFT) : '00000') . (isset($dst_h) ? str_pad((string) $dst_h, 5, '0', STR_PAD_LEFT) : '00000') . str_pad(preg_replace('#^\\##', '', $canvas_color), 8, '0', STR_PAD_LEFT) . str_pad((string) $quality, 3, '0', STR_PAD_LEFT);
     $log->add('image_file_hash', 'Hash: ' . $hash);
     // Hash the filename suffix.
     $suffix = md5($hash);
     $log->add('image_base_name_suffix', 'Base filename suffix: ' . $suffix);
     // Use this to check if cropped image already exists, so we can return that instead.
     $dst_rel_path = str_replace('.' . $ext, '', $image_info['basename']);
     // Set file ext to `png` if the opacity has been set less than 100 or if the crop mode is `2` and the canvas color was set to transparent.
     if ($opacity < 100 || $canvas_color === 'transparent' && $crop_mode == 2) {
         $ext = 'png';
     }
     // Create the upload subdirectory, this is where the generated images are saved.
     $upload_dir = is_string($atts['sub_dir']) && !empty($atts['sub_dir']) ? trailingslashit(CN_IMAGE_PATH . $atts['sub_dir']) : CN_IMAGE_PATH;
     $upload_url = is_string($atts['sub_dir']) && !empty($atts['sub_dir']) ? trailingslashit(CN_IMAGE_BASE_URL . $atts['sub_dir']) : CN_IMAGE_BASE_URL;
     cnFileSystem::mkdir($upload_dir);
     // Destination paths and URL.
     $destfilename = "{$upload_dir}{$dst_rel_path}-{$suffix}." . strtolower($ext);
     $img_url = "{$upload_url}{$dst_rel_path}-{$suffix}." . strtolower($ext);
     // If file exists, just return it.
     if (@file_exists($destfilename) && ($image_info = getimagesize($destfilename))) {
         $mime_type = $image_info['mime'];
         $log->add('image_serve_from_cache', 'Image found in cache, no processing required.');
         $editor = wp_get_image_editor($destfilename);
         // If there is an error, return WP_Error object.
         if (is_wp_error($editor)) {
             return $editor;
         }
         $log->add('image_editor_engine', __(sprintf('Image processing parent class is %s', get_parent_class($editor)), 'connections'));
         $log->add('image_editor_engine', __(sprintf('Image processing class is %s', get_class($editor)), 'connections'));
     } else {
         // Setup the $methods var to be passed to wp_get_image_editor()
         // so the correct image editor engine can be chosen for processing the image.
         if ($negate) {
             $methods['methods'][] = 'negate';
         }
         if ($grayscale) {
             $methods['methods'][] = 'grayscale';
         }
         if (isset($brightness)) {
             $methods['methods'][] = 'brightness';
         }
         if (isset($colorize)) {
             $methods['methods'][] = 'colorize';
         }
         if (isset($contrast)) {
             $methods['methods'][] = 'contrast';
         }
         if ($detect_edges) {
             $methods['methods'][] = 'detect_edges';
         }
         if ($emboss) {
             $methods['methods'][] = 'emboss';
         }
         if ($gaussian_blur) {
             $methods['methods'][] = 'gaussian_blur';
         }
         if ($blur) {
             $methods['methods'][] = 'blur';
         }
         if ($sketchy) {
             $methods['methods'][] = 'sketchy';
         }
         if ($sharpen) {
             $methods['methods'][] = 'sharpen';
         }
         if (isset($smooth)) {
             $methods['methods'][] = 'smooth';
         }
         if (isset($opacity)) {
             $methods['methods'][] = 'opacity';
         }
         if ($crop_focus) {
             $methods['methods'][] = 'crop';
         }
         if ($crop_mode == 2) {
             $methods['methods'][] = 'resize_padded';
         }
         if ($crop_only) {
             $methods['methods'][] = 'resize';
         }
         $methods['methods'][] = 'set_quality';
         // Perform resizing and other filters.
         /** @var CN_Image_Editor_GD $editor */
         $editor = wp_get_image_editor($image_info['path'], $methods);
         // If there is an error, return WP_Error object.
         if (is_wp_error($editor)) {
             return $editor;
         }
         $log->add('image_editor_engine', __(sprintf('Image processing parent class is %s', get_parent_class($editor)), 'connections'));
         $log->add('image_editor_engine', __(sprintf('Image processing class is %s', get_class($editor)), 'connections'));
         /*
          * Perform image manipulations.
          */
         if ($crop_only === FALSE) {
             if (!empty($width) && $width || !empty($height) && $height) {
                 switch ($crop_mode) {
                     case 0:
                         if (is_wp_error($result = $editor->resize(empty($width) ? NULL : $width, empty($height) ? NULL : $height, FALSE))) {
                             return $result;
                         }
                         $log->add('image_resized', __('Image successfully resized to fit new width and height without maintaining proportion.', 'connections'));
                         break;
                     case 1:
                         if (is_wp_error($result = $editor->resize(empty($width) ? NULL : $width, empty($height) ? NULL : $height, is_array($crop_focus) ? $crop_focus : TRUE))) {
                             return $result;
                         }
                         if (is_bool($crop_focus)) {
                             $log->add('image_resized', __('Image successfully resized with cropping.', 'connections'));
                         } elseif (is_array($crop_focus)) {
                             $log->add('image_resized', __(sprintf('Image successfully resized with cropping from origin %s,%s.', $crop_focus[0], $crop_focus[1]), 'connections'));
                         }
                         break;
                     case 2:
                         if (is_wp_error($result = $editor->resize_padded($canvas_w, $canvas_h, $canvas_color, empty($width) ? NULL : $width, empty($height) ? NULL : $height, $orig_w, $orig_h, empty($origin_x) ? 0 : $origin_x, empty($origin_y) ? 0 : $origin_y))) {
                             return $result;
                         }
                         $log->add('image_resized', __('Image successfully resized proportionally with padding.', 'connections'));
                         break;
                     case 3:
                         if (is_wp_error($result = $editor->resize(empty($width) ? NULL : $width, empty($height) ? NULL : $height, FALSE))) {
                             return $result;
                         }
                         $log->add('image_resized', __('Image successfully resized proportionally with no padding.', 'connections'));
                         break;
                 }
             }
         } else {
             if (is_wp_error($result = $editor->crop($src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h))) {
                 return $result;
             }
         }
         if ($negate) {
             if (is_wp_error($result = $editor->negate())) {
                 return $result;
             }
             $log->add('image_filter_negate', __('Negate filter applied.', 'connections'));
         }
         if ($grayscale) {
             if (is_wp_error($result = $editor->grayscale())) {
                 return $result;
             }
             $log->add('image_filter_grayscale', __('Grayscale filter applied.', 'connections'));
         }
         if (isset($brightness)) {
             if (is_wp_error($result = $editor->brightness($brightness))) {
                 return $result;
             }
             $log->add('image_filter_brightnes', __(sprintf('Brightness level %s applied.', $brightness), 'connections'));
         }
         if (isset($contrast)) {
             if (is_wp_error($result = $editor->contrast($contrast))) {
                 return $result;
             }
             $log->add('image_filter_contrast', __(sprintf('Contrast level %s applied.', $contrast), 'connections'));
         }
         if (isset($colorize)) {
             if (is_wp_error($result = $editor->colorize($colorize))) {
                 return $result;
             }
             $log->add('image_filter_colorize', __(sprintf('Colorized using %s.', $colorize), 'connections'));
         }
         if ($detect_edges) {
             if (is_wp_error($result = $editor->detect_edges())) {
                 return $result;
             }
             $log->add('image_filter_edge_detect', __('Edge Detect filter applied.', 'connections'));
         }
         if ($emboss) {
             if (is_wp_error($result = $editor->emboss())) {
                 return $result;
             }
             $log->add('image_filter_emboss', __('Emboss filter applied.', 'connections'));
         }
         if ($gaussian_blur) {
             if (is_wp_error($result = $editor->gaussian_blur())) {
                 return $result;
             }
             $log->add('image_filter_gaussian_blur', __('Gaussian Blur filter applied.', 'connections'));
         }
         if ($blur) {
             if (is_wp_error($result = $editor->blur())) {
                 return $result;
             }
             $log->add('image_filter_blur', __('Blur filter applied.', 'connections'));
         }
         if ($sketchy) {
             if (is_wp_error($result = $editor->sketchy())) {
                 return $result;
             }
             $log->add('image_filter_sketchy', __('Sketchy filter applied.', 'connections'));
         }
         if ($sharpen) {
             if (is_wp_error($result = $editor->sharpen($sharpen))) {
                 return $result;
             }
             $log->add('image_filter_sharpen', __('Sharpen filter applied.', 'connections'));
         }
         if (isset($smooth)) {
             if (is_wp_error($result = $editor->smooth($smooth))) {
                 return $result;
             }
             $log->add('image_filter_smooth', __(sprintf('Smooth filter applied with level %s.', $smooth), 'connections'));
         }
         if ($opacity < 100) {
             if (is_wp_error($result = $editor->opacity($opacity))) {
                 return $result;
             }
         }
         $log->add('image_filter_opacity', __(sprintf('Opacity set at %d.', $opacity), 'connections'));
         // Set image save quality.
         $editor->set_quality($quality);
         $log->add('image_save_quality', __(sprintf('Saving quality set at %s.', $editor->get_quality()), 'connections'));
         // Save the new image, set file type to PNG if the opacity has been set less than 100 or if the crop mode is `2` and the canvas color was set to transparent.
         if ($opacity < 100 || $canvas_color === 'transparent' && $crop_mode == 2 || $orig_mime_type == 'image/png') {
             $mime_type = 'image/png';
         } elseif ($orig_mime_type == 'image/jpeg') {
             $mime_type = 'image/jpeg';
         } elseif ($orig_mime_type == 'image/gif') {
             $mime_type = 'image/gif';
         }
         $log->add('image_save_mime_type', __(sprintf('Saving file as %s.', $mime_type), 'connections'));
         $log->add('image_save_file_path', __(sprintf('Saving file in path: %s', $destfilename), 'connections'));
         $resized_file = $editor->save($destfilename, $mime_type);
         $log->add('image_save', __('File saved successfully.', 'connections'));
     }
     $log->add('image_cache_url', __(sprintf('Cache URL: %s', $img_url), 'connections'));
     /*
      * Remove the cnImage filters.
      */
     remove_filter('wp_image_editors', array(__CLASS__, 'imageEditors'));
     remove_filter('image_resize_dimensions', array(__CLASS__, 'resize_dimensions'), 10);
     /*
      * Be a good citizen and add the filters that were hooked back to image editor filters.
      */
     if (!empty($filter['editors'])) {
         $wp_filter['wp_image_editors'] = $filter['editors'];
     }
     if (!empty($filter['resize'])) {
         $wp_filter['image_resize_dimensions'] = $filter['resize'];
     }
     switch ($return) {
         case 'base64':
             $image = 'data:image/' . (isset($mime_type) ? $mime_type : $orig_mime_type) . ';base64,' . base64_encode(file_get_contents($destfilename));
             break;
         case 'data':
             $image = array('name' => "{$dst_rel_path}-{$suffix}.{$ext}", 'path' => $destfilename, 'url' => $img_url, 'width' => isset($dst_w) ? $dst_w : $orig_w, 'height' => isset($dst_h) ? $dst_h : $orig_h, 'size' => 'height="' . (isset($dst_h) ? $dst_h : $orig_h) . '" width="' . (isset($dst_w) ? $dst_w : $orig_w) . '"', 'mime' => isset($mime_type) ? $mime_type : $orig_mime_type, 'type' => $image_info[2], 'log' => defined('WP_DEBUG') && WP_DEBUG === TRUE ? $log : __('WP_DEBUG is not defined or set to FALSE, set to TRUE to enable image processing log.', 'connections'));
             break;
         case 'editor':
             $image = $editor;
             break;
         case 'stream':
             $image = $editor->stream();
             break;
         default:
             $image = $img_url;
             break;
     }
     return $image;
 }
 /**
  * Displays the category list in a HTML list or custom format.
  *
  * NOTE: This is the Connections equivalent of @see get_the_category_list() in WordPress core ../wp-includes/category-template.php
  *
  * @access public
  * @since  unknown
  *
  * @param array $atts {
  * Optional. An array of arguments.
  *
  *     @type string $container_tag    The HTML tag to be used for the container element.
  *                                    Default: div
  *     @type string $label_tag        The HTML tag to be used for the category label element.
  *                                    Default: span
  *     @type string $item_tag         The HTML tag to be used for the category element.
  *                                    Default: span
  *     @type string $type             The display type to be used to display the categories.
  *                                    Accepts: block|list
  *                                    Default: block
  *     @type string $list             If the $type is list, which type?
  *                                    Accepts: ordered|unordered
  *                                    Default: unordered
  *     @type string $label            The label to be displayed before the categories.
  *                                    Default: Categories:
  *     @type string $separator        The category separator used when separating categories when $type == list
  *                                    Default: ', '
  *     @type string $parent_separator The separator to be used when displaying the category's hierarchy.
  *                                    Default: ' &raquo; '
  *     @type string $before           String content to display before the categories.
  *     @type string $after            String content to display after the categories.
  *     @type bool   $link             Whether or not render the categories as permalinks.
  *                                    Default: false
  *     @type bool   $parents          Whether or not to display the category hierarchy.
  *                                    Default: false
  *     @type bool   $return           Whether or not to echo or return the HTML.
  *                                    Default: false
  * }
  *
  * @return string
  */
 public function getCategoryBlock($atts = array())
 {
     global $wp_rewrite;
     $defaults = array('container_tag' => 'div', 'label_tag' => 'span', 'item_tag' => 'span', 'type' => 'block', 'list' => 'unordered', 'label' => __('Categories:', 'connections') . ' ', 'separator' => ', ', 'parent_separator' => ' &raquo; ', 'before' => '', 'after' => '', 'link' => FALSE, 'parents' => FALSE, 'return' => FALSE);
     /**
      * All extensions to filter the method default and supplied args.
      *
      * @since 8.5.18
      */
     $atts = cnSanitize::args(apply_filters('cn_output_atts_category', $atts), apply_filters('cn_output_default_atts_category', $defaults));
     $categories = $this->getCategory();
     $count = count($categories);
     $html = '';
     $label = '';
     $items = array();
     if (empty($categories)) {
         return $html;
     }
     if ('list' == $atts['type']) {
         $atts['item_tag'] = 'li';
     }
     if (0 < strlen($atts['label'])) {
         $label = sprintf('<%1$s class="cn_category_label">%2$s</%1$s> ', $atts['label_tag'], esc_html($atts['label']));
     }
     $i = 1;
     foreach ($categories as $category) {
         $text = '';
         if ($atts['parents']) {
             // If the term is a root parent, skip.
             if (0 !== $category->parent) {
                 $text .= cnTemplatePart::getCategoryParents($category->parent, array('link' => $atts['link'], 'separator' => $atts['parent_separator'], 'force_home' => $this->directoryHome['force_home'], 'home_id' => $this->directoryHome['page_id']));
             }
         }
         if ($atts['link']) {
             $rel = is_object($wp_rewrite) && $wp_rewrite->using_permalinks() ? 'rel="category tag"' : 'rel="category"';
             $url = cnTerm::permalink($category, 'category', array('force_home' => $this->directoryHome['force_home'], 'home_id' => $this->directoryHome['page_id']));
             $text .= '<a href="' . $url . '" ' . $rel . '>' . esc_html($category->name) . '</a>';
         } else {
             $text .= esc_html($category->name);
         }
         $items[] = apply_filters('cn_entry_output_category_item', sprintf('<%1$s class="cn-category-name cn_category cn-category-%2$d">%3$s%4$s</%1$s>', $atts['item_tag'], $category->term_id, $text, $count > $i && 'list' !== $atts['type'] ? esc_html($atts['separator']) : ''), $category, $count, $i, $atts, $this);
         $i++;
         // Increment here so the correct value is passed to the filter.
     }
     /*
      * Remove NULL, FALSE and empty strings (""), but leave values of 0 (zero).
      * Filter our these in case someone hooks into the `cn_entry_output_category_item` filter and removes a category
      * by returning an empty value.
      */
     $items = array_filter($items, 'strlen');
     if ('list' == $atts['type']) {
         $html .= sprintf('<%1$s class="cn-category-list">%2$s</%1$s>', 'unordered' === $atts['list'] ? 'ul' : 'ol', implode('', $items));
     } else {
         $html .= implode('', $items);
     }
     $html = apply_filters('cn_entry_output_category_container', sprintf('<%1$s class="cn-categories">%2$s</%1$s>' . PHP_EOL, $atts['container_tag'], $atts['before'] . $label . $html . $atts['after']), $atts);
     return $this->echoOrReturn($atts['return'], $html);
 }
 /**
  * Sanitize use input based in field type.
  *
  * @access private
  * @since 0.8
  *
  * @return mixed
  */
 public function sanitize($type, $value, $options = array(), $default = NULL)
 {
     switch ($type) {
         case 'checkbox':
             $value = cnSanitize::checkbox($value);
             break;
         case 'checkboxgroup':
             $value = cnSanitize::options($value, $options, $default);
             break;
         case 'radio':
             $value = cnSanitize::option($value, $options, $default);
             break;
         case 'radio_inline':
             $value = cnSanitize::option($value, $options, $default);
             break;
         case 'select':
             $value = cnSanitize::option($value, $options, $default);
             break;
         case 'text':
             $value = cnSanitize::string('text', $value);
             break;
         case 'textarea':
             $value = cnSanitize::string('textarea', $value);
             break;
         case 'slider':
             $value = absint($value);
             break;
         case 'colorpicker':
             $value = cnSanitize::string('color', $value);
             break;
         case 'quicktag':
             $value = cnSanitize::string('quicktag', $value);
             break;
         case 'rte':
             $value = cnSanitize::string('html', $value);
             break;
         default:
             $value = apply_filters('cn_meta_sanitize_field-' . $type, $value, $options, $default);
             break;
     }
     return $value;
 }
 /**
  * Displays the category list in a HTML list or custom format
  *
  * @TODO: Implement $parents.
  *
  * Accepted option for the $atts property are:
  *   list == string -- The list type to output. Accepted values are ordered || unordered.
  *   separator == string -- The category separator.
  *   before == string -- HTML to output before the category list.
  *   after == string -- HTML to output after the category list.
  *   label == string -- String to display after the before attribute but before the category list.
  *   parents == bool -- Display the parents
  *   return == TRUE || FALSE -- Return string if set to TRUE instead of echo string.
  *
  * @access public
  * @since  unknown
  *
  * @param array $atts
  *
  * @return string
  */
 public function getCategoryBlock($atts = array())
 {
     $defaults = array('list' => 'unordered', 'separator' => NULL, 'before' => '', 'after' => '', 'label' => __('Categories:', 'connections') . ' ', 'parents' => FALSE, 'return' => FALSE);
     $defaults = apply_filters('cn_output_default_atts_category', $defaults);
     $atts = cnSanitize::args($atts, $defaults);
     $out = '';
     $categories = $this->getCategory();
     if (empty($categories)) {
         return $out;
     }
     $out .= '<div class="cn-categories">';
     $out .= $atts['before'];
     if (!empty($atts['label'])) {
         $out .= '<span class="cn_category_label">' . $atts['label'] . '</span> ';
     }
     if (is_null($atts['separator'])) {
         $out .= $atts['list'] === 'unordered' ? '<ul class="cn_category_list">' : '<ol class="cn_category_list">';
         foreach ($categories as $category) {
             $out .= '<li class="cn_category" id="cn_category_' . $category->term_id . '">' . $category->name . '</li>';
         }
         $out .= $atts['list'] === 'unordered' ? '</ul>' : '</ol>';
     } else {
         $count = count($categories);
         $i = 1;
         foreach ($categories as $category) {
             // The `cn_category` class is named with an underscore for backward compatibility.
             $out .= sprintf('<span class="cn-category-name cn_category" id="cn-category-%1$d">%2$s%3$s</span>', $category->term_id, esc_html($category->name), $count > $i++ && !is_null($atts['separator']) ? $atts['separator'] : '');
         }
     }
     $out .= $atts['after'];
     $out .= '</div>';
     return $this->echoOrReturn($atts['return'], $out);
 }
 /**
  * Displays the category list in a HTML list or custom format
  *
  * @TODO: Implement $parents.
  *
  * Accepted option for the $atts property are:
  *   list == string -- The list type to output. Accepted values are ordered || unordered.
  *   separator == string -- The category separator.
  *   before == string -- HTML to output before the category list.
  *   after == string -- HTML to output after the category list.
  *   label == string -- String to display after the before attribute but before the category list.
  *   parents == bool -- Display the parents
  *   return == TRUE || FALSE -- Return string if set to TRUE instead of echo string.
  *
  * @access public
  * @since  unknown
  *
  * @param array $atts
  *
  * @return string
  */
 public function getCategoryBlock($atts = array())
 {
     $defaults = array('list' => 'unordered', 'separator' => NULL, 'before' => '', 'after' => '', 'label' => __('Categories:', 'connections') . ' ', 'parents' => FALSE, 'return' => FALSE);
     $defaults = apply_filters('cn_output_default_atts_category', $defaults);
     $atts = cnSanitize::args($atts, $defaults);
     $out = '';
     $categories = $this->getCategory();
     if (empty($categories)) {
         return $out;
     }
     $out .= $atts['before'];
     if (!empty($atts['label'])) {
         $out .= '<span class="cn_category_label">' . $atts['label'] . '</span>';
     }
     if (empty($atts['separator'])) {
         $atts['list'] === 'unordered' ? $out .= '<ul class="cn_category_list">' : ($out .= '<ol class="cn_category_list">');
         foreach ($categories as $category) {
             $out .= '<li class="cn_category" id="cn_category_' . $category->term_id . '">' . $category->name . '</li>';
         }
         $atts['list'] === 'unordered' ? $out .= '</ul>' : ($out .= '</ol>');
     } else {
         $i = 1;
         foreach ($categories as $category) {
             $out .= '<span class="cn_category" id="cn_category_' . $category->term_id . '">' . $category->name . (count($categories) > $i++ && !empty($atts['separator']) ? $atts['separator'] : '') . '</span>';
         }
     }
     $out .= $atts['after'];
     return $this->echoOrReturn($atts['return'], $out);
 }
 /**
  * Set the entry notes.
  *
  * @access public
  * @since  unknown
  *
  * @param string $notes
  * @param string $context
  */
 public function setNotes($notes, $context = 'db')
 {
     $this->notes = cnSanitize::field('notes', $notes, $context);
 }
 /**
  * Tints the image a different color
  *
  * @access public
  * @since  8.1
  *
  * @param string $hexColor hex color e.g. #ff00ff
  * @return boolean|WP_Error
  */
 public function colorize($hexColor)
 {
     $hexColor = cnSanitize::hexColor($hexColor);
     if (empty($hexColor)) {
         return new WP_Error('image_colorize_error', __('Value passed to ' . get_class($this) . '::colorize() is an invalid hex color.', 'connections'), $this->file);
     }
     try {
         // When you're using an image with an alpha channel (for example a transparent png), a value of 1.0 will return a completely transparent image,
         // but a value of 1 works just fine.
         // ref: http://php.net/manual/en/imagick.colorizeimage.php#107012
         return $this->image->colorizeImage($hexColor, 1);
     } catch (Exception $e) {
         return new WP_Error('image_colorize_error', $e->getMessage(), $this->file);
     }
 }
 /**
  * Total record count based on current user permissions.
  *
  * @access public
  * @since  unknown
  *
  * @global $wpdb
  * @global $connections
  *
  * @uses   wp_parse_args()
  * @uses   is_user_logged_in()
  * @uses   current_user_can()
  * @uses   $wpdb->get_var()
  *
  * @param  (array)
  *
  * @return int
  */
 public static function recordCount($atts)
 {
     /**  @var wpdb $wpdb */
     global $wpdb;
     $where[] = 'WHERE 1=1';
     $defaults = array('public_override' => TRUE, 'private_override' => TRUE, 'status' => array());
     $atts = cnSanitize::args($atts, $defaults);
     $where = self::setQueryVisibility($where, $atts);
     $where = self::setQueryStatus($where, $atts);
     $results = $wpdb->get_var('SELECT COUNT(`id`) FROM ' . CN_ENTRY_TABLE . ' ' . implode(' ', $where));
     return !empty($results) ? $results : 0;
 }
 /**
  * Generates a permalink for a taxonomy term.
  *
  * Filters:
  *    cn_term_link
  *        Passes: (string) $link, (object) $term, (string) $taxonomy
  *        Return: $link
  *
  * NOTE: This is the Connections equivalent of get_term_link() in WordPress core ../wp-includes/taxonomy.php
  *
  * @access public
  * @since  8.1.6
  * @static
  *
  * @uses   cnTerm::get()
  * @uses   cnTerm::getBy()
  * @uses   is_wp_error()
  * @uses   cnTerm::getAncestors()
  * @uses   cnURL::permalink()
  * @uses   apply_filters()
  *
  * @param object|int|string $term
  * @param string            $taxonomy (optional if $term is object)
  * @param array             $atts
  *
  * @return string|WP_Error URL  to taxonomy term on success, WP_Error if term does not exist.
  */
 public static function permalink($term, $taxonomy = '', $atts = array())
 {
     /** @var $wp_rewrite WP_Rewrite */
     //global $wp_rewrite;
     $defaults = array('force_home' => FALSE, 'home_id' => cnSettingsAPI::get('connections', 'connections_home_page', 'page_id'));
     $atts = cnSanitize::args($atts, $defaults);
     if (!is_object($term)) {
         if (is_int($term)) {
             $term = self::get($term, $taxonomy);
         } else {
             $term = self::getBy('slug', $term, $taxonomy);
         }
     }
     if (!is_object($term)) {
         $term = new WP_Error('invalid_term', __('Empty Term', 'connections'));
     }
     if (is_wp_error($term)) {
         return $term;
     }
     $taxonomy = $term->taxonomy;
     //$link = $wp_rewrite->get_extra_permastruct( $taxonomy );
     //$slug = $term->slug;
     //$t    = get_taxonomy( $taxonomy );
     //if ( empty( $link ) ) {
     //if ( 'category' == $taxonomy ) {
     //$link = '?cat=' . $term->term_id;
     //} elseif ( $t->query_var ) {
     //
     //	$term_link = "?$t->query_var=$slug";
     //} else {
     //	$link = "?taxonomy=$taxonomy&term=$slug";
     //}
     //$link = home_url( $link );
     //} else {
     //if ( $t->rewrite['hierarchical'] ) {
     $slugs = array();
     $ancestors = self::getAncestors($term->term_id, $taxonomy);
     foreach ((array) $ancestors as $ancestor) {
         $ancestor_term = self::get($ancestor, $taxonomy);
         $slugs[] = $ancestor_term->slug;
     }
     $slugs = array_reverse($slugs);
     $slugs[] = $term->slug;
     $link = cnURL::permalink(array('type' => 'category', 'slug' => implode('/', $slugs), 'title' => $term->name, 'text' => $term->name, 'data' => 'url', 'force_home' => $atts['force_home'], 'home_id' => $atts['home_id'], 'return' => TRUE));
     //} else {
     //
     //	$term_link = str_replace( "%$taxonomy%", $slug, $term_link );
     //}
     //$link = home_url( user_trailingslashit( $link, 'category' ) );
     //}
     /**
      * Filter the term link.
      *
      * @since 8.1.6
      *
      * @param string $link Term link URL.
      * @param object $term     Term object.
      * @param string $taxonomy Taxonomy slug.
      */
     return apply_filters('cn_term_link', $link, $term, $taxonomy);
 }
 /**
  * Retrieve category parents with separator.
  *
  * NOTE: This is the Connections equivalent of @see get_category_parents() in WordPress core ../wp-includes/category-template.php
  *
  * @access public
  * @since  8.5.18
  * @static
  *
  * @param int    $id        Category ID.
  * @param array  $atts      The attributes array. {
  *
  *     @type bool   $link       Whether to format as link or as a string.
  *                              Default: FALSE
  *     @type string $separator  How to separate categories.
  *                              Default: '/'
  *     @type bool   $nicename   Whether to use nice name for display.
  *                              Default: FALSE
  *     @type array  $visited    Already linked to categories to prevent duplicates.
  *                              Default: array()
  *     @type bool   $force_home Default: FALSE
  *     @type int    $home_id    Default: The page set as the directory home page.
  * }
  *
  * @return string|WP_Error A list of category parents on success, WP_Error on failure.
  */
 public static function getCategoryParents($id, $atts = array())
 {
     $defaults = array('link' => FALSE, 'separator' => '/', 'nicename' => FALSE, 'visited' => array(), 'force_home' => FALSE, 'home_id' => cnSettingsAPI::get('connections', 'connections_home_page', 'page_id'));
     $atts = cnSanitize::args($atts, $defaults);
     $chain = '';
     $parent = cnTerm::get($id, 'category');
     if (is_wp_error($parent)) {
         return $parent;
     }
     if ($atts['nicename']) {
         $name = $parent->slug;
     } else {
         $name = $parent->name;
     }
     if ($parent->parent && $parent->parent != $parent->term_id && !in_array($parent->parent, $atts['visited'])) {
         $atts['visited'][] = $parent->parent;
         $chain .= self::getCategoryParents($parent->parent, $atts);
     }
     if ($atts['link']) {
         $chain .= '<a href="' . esc_url(cnTerm::permalink($parent->term_id, 'category', $atts)) . '">' . $name . '</a>' . $atts['separator'];
     } else {
         $chain .= $name . esc_html($atts['separator']);
     }
     return $chain;
 }
 /**
  * Create an array to store the which records by visibility the user can edit.
  * This is done to prevent deleting any records the user isn't permitted view.
  *
  * @access private
  * @since  8.2.6
  *
  * @global $wpdb
  *
  * @uses   cnEntry_DB::sanitizeID()
  * @uses   wpdb::query()
  *
  * @param string $table The table from which to delete the rows from.
  * @param array  $data  An array of unique ID/s to delete from the defined table.
  */
 private function upsertDelete($table, $data)
 {
     /** @var wpdb $wpdb */
     global $wpdb;
     $permitted = array();
     $where = array('WHERE 1=1');
     $where[] = 'AND `entry_id` = "' . $this->id . '"';
     if (current_user_can('connections_view_public')) {
         $permitted[] = 'public';
     }
     if (current_user_can('connections_view_private')) {
         $permitted[] = 'private';
     }
     if (current_user_can('connections_view_unlisted')) {
         $permitted[] = 'unlisted';
     }
     if (!empty($permitted)) {
         $where[] = 'AND `visibility` IN (\'' . implode('\', \'', $permitted) . '\')';
     }
     $id = cnSanitize::id($data);
     if (!empty($id)) {
         $where[] = 'AND `id` NOT IN ( ' . implode(', ', $id) . ' )';
     }
     $wpdb->query("DELETE FROM `{$table}` " . implode(' ', $where));
 }
 /**
  * Email the system info.
  *
  * @access private
  * @since  8.3
  * @static
  *
  * @uses   add_filter()
  * @uses   cnEmail()
  * @uses   sanitize_email()
  * @uses   sanitize_text_field()
  * @uses   esc_html()
  * @uses   cnSystem_Info::get()
  * @uses   remove_filter()
  *
  * @param array $atts {
  *     @type string $from_email The "from" email address.
  *     @type string $from_name  The "from" name.
  *     @type string $to_email   The "to" email address.
  *     @type string $to_name    The "to" name.
  *     @type string $subject    The email subject.
  *     @type string $message    The message to precede the system info.
  * }
  *
  * @return bool
  */
 public static function email($atts)
 {
     $defaults = array('from_email' => '', 'from_name' => '', 'to_name' => '', 'to_email' => '', 'subject' => '', 'message' => '');
     $atts = cnSanitize::args($atts, $defaults);
     $email = new cnEmail();
     // Set email to be sent as HTML.
     $email->HTML();
     // Set from whom.
     $email->from(sanitize_email($atts['from_email']), sanitize_text_field($atts['from_name']));
     // Set to whom.
     $email->to(sanitize_email($atts['to_email']));
     // Set the subject.
     $email->subject(sanitize_text_field($atts['subject']));
     $message = sanitize_text_field($atts['message']);
     $message .= PHP_EOL . PHP_EOL;
     $message .= '<pre>' . esc_html(self::get()) . '</pre>';
     // Set the message.
     $email->message($message);
     add_filter('cn_email_header', array(__CLASS__, 'setEmailHeader'));
     $response = $email->send();
     remove_filter('cn_email_header', array(__CLASS__, 'setEmailHeader'));
     return $response;
 }
 /**
  * Start the element output.
  *
  * @see   Walker::start_el()
  *
  * @since 8.1.6
  *
  * @uses   esc_attr()
  * @uses   number_format_i18n()
  * @uses   cnTerm::get()
  *
  * @param string $output Passed by reference. Used to append additional content.
  * @param object $term   Term object.
  * @param int    $depth  Depth of category in reference to parents. Default 0.
  * @param array  $args   An array of arguments. @see CN_Walker_Term_List::render()
  * @param int    $id     ID of the current term.
  */
 public function start_el(&$output, $term, $depth = 0, $args = array(), $id = 0)
 {
     $indent = str_repeat("\t", $depth);
     $count = $args['show_count'] ? '<span class="cn-cat-count">&nbsp;(' . esc_html(number_format_i18n($term->count)) . ')</span>' : '';
     $url = cnTerm::permalink($term, 'category', $args);
     $html = sprintf('<a href="%1$s" title="%2$s">%3$s</a>', $url, esc_attr($term->name), esc_html($term->name) . $count);
     /**
      * Allows extensions to alter the HTML of term list item.
      *
      * @since 8.5.18
      *
      * @param string        $html  The HTML.
      * @param cnTerm_Object $term  The current term.
      * @param int           $depth Depth of category. Used for tab indentation.
      * @param array         $args  The method attributes.
      */
     $html = apply_filters('cn_term_list_item', $html, $term, $depth, $args);
     $class = array('cat-item', 'cat-item-' . $term->term_id, 'cn-cat-parent');
     $termChildren = cnTerm::getTaxonomyTerms($term->taxonomy, array('parent' => $term->term_id, 'hide_empty' => FALSE, 'fields' => 'count'));
     if (!empty($termChildren)) {
         $class[] = 'cn-cat-has-children';
     }
     if (!empty($args['current_category'])) {
         if (is_numeric($args['current_category'])) {
             $_current_category = cnTerm::get($args['current_category'], $term->taxonomy);
             // cnTerm::get() can return NULL || an instance of WP_Error, so, lets check for that.
             if (is_null($_current_category) || is_wp_error($_current_category)) {
                 $_current_category = new stdClass();
                 $_current_category->parent = 0;
             }
         } else {
             $_current_category = new stdClass();
             $_current_category->parent = 0;
         }
         if ($term->slug == $args['current_category']) {
             $class[] = ' current-cat';
         } elseif ($term->term_id == $args['current_category']) {
             $class[] = ' current-cat';
         } elseif ($term->term_id == $_current_category->parent) {
             $class[] = ' current-cat-parent';
         }
     }
     /**
      * Allows extensions to add/remove class names to the current term list item.
      *
      * @since 8.5.18
      *
      * @param array         $class The array of class names.
      * @param cnTerm_Object $term  The current term.
      * @param int           $depth Depth of category. Used for tab indentation.
      * @param array         $args  The method attributes.
      */
     $class = apply_filters('cn_term_list_item_class', $class, $term, $depth, $args);
     $class = cnSanitize::htmlClass($class);
     $output .= "{$indent}<li" . ' class="' . cnFunction::escAttributeDeep($class) . '"' . ">{$html}";
     // Do not add EOL here, it'll add unwanted whitespace if terms are inline.
 }
 /**
  * Callback function to sanitize the image settings.
  *
  * @access private
  * @since  0.7.7
  *
  * @param array $settings
  *
  * @return array
  */
 public static function sanitizeImageSettings($settings)
 {
     $defaults = array('quality' => 80, 'height' => 150, 'width' => 225, 'ratio' => 'crop');
     $settings = cnSanitize::args($settings, $defaults);
     // Ensure positive int values
     $settings['quality'] = absint($settings['quality']);
     $settings['height'] = absint($settings['height']);
     $settings['width'] = absint($settings['width']);
     // If the values is empty, set a default.
     $settings['quality'] = empty($settings['quality']) ? 80 : $settings['quality'];
     $settings['height'] = empty($settings['height']) ? 150 : $settings['height'];
     $settings['width'] = empty($settings['width']) ? 225 : $settings['width'];
     // The valid ratio options
     $ratio = array('crop', 'fill', 'fit', 'none');
     // Make sure the value is one of the permitted options and if it is not, set it to the 'crop' value.
     $settings['ratio'] = in_array($settings['ratio'], $ratio) ? $settings['ratio'] : 'crop';
     return $settings;
 }
/**
 * Display the upcoming list.
 *
 * @access public
 * @since  unknown
 *
 * @param array  $atts
 * @param string $content [optional]
 * @param string $tag     [optional] When called as the callback for add_shortcode, the shortcode tag is passed
 *                        automatically. Manually setting the shortcode tag so the function can be called
 *                        independently.
 *
 * @return string
 */
function _upcoming_list($atts, $content = NULL, $tag = 'upcoming_list')
{
    global $connections, $wpdb;
    // $template =& $connections->template;
    $out = '';
    $alternate = '';
    $templateTypeDefaults = array('list_type' => 'birthday', 'template' => NULL);
    $templateType = cnSanitize::args($atts, $templateTypeDefaults);
    /*
     * If a list type was specified in the shortcode, load the template based on that type.
     * However, if a specific template was specified, that should preempt the template to be loaded based on the list type if it was specified..
     */
    if (!empty($atts['template'])) {
        $template = cnTemplateFactory::getTemplate($templateType['template']);
    } else {
        $templateSlug = $connections->options->getActiveTemplate($templateType['list_type']);
        $template = cnTemplateFactory::getTemplate($templateSlug);
    }
    // No template found return error message.
    if ($template === FALSE) {
        return cnTemplatePart::loadTemplateError($templateType);
    }
    $defaults = array('list_type' => 'birthday', 'days' => '30', 'include_today' => TRUE, 'private_override' => FALSE, 'name_format' => '', 'date_format' => 'F jS', 'show_lastname' => FALSE, 'show_title' => TRUE, 'list_title' => NULL, 'template' => NULL, 'content' => '', 'force_home' => TRUE, 'home_id' => cnSettingsAPI::get('connections', 'home_page', 'page_id'));
    $defaults = apply_filters('cn_list_atts_permitted', $defaults);
    $defaults = apply_filters('cn_list_atts_permitted-' . $template->getSlug(), $defaults);
    $atts = shortcode_atts($defaults, $atts, $tag);
    $atts = apply_filters('cn_list_atts', $atts);
    $atts = apply_filters('cn_list_atts-' . $template->getSlug(), $atts);
    /*
     * Convert some of the $atts values in the array to boolean.
     */
    cnFormatting::toBoolean($atts['include_today']);
    cnFormatting::toBoolean($atts['private_override']);
    cnFormatting::toBoolean($atts['show_lastname']);
    cnFormatting::toBoolean($atts['repeat_alphaindex']);
    cnFormatting::toBoolean($atts['show_title']);
    if (0 == strlen($atts['name_format'])) {
        $atts['name_format'] = $atts['show_lastname'] ? '%first% %last%' : '%first%';
    }
    /** @var cnTemplate $template */
    do_action('cn_register_legacy_template_parts');
    do_action('cn_action_include_once-' . $template->getSlug());
    do_action('cn_action_js-' . $template->getSlug());
    /*
     * This filter adds the current template paths to cnLocate so when template
     * part file overrides are being searched for, it'll also search in template
     * specific paths. This filter is then removed at the end of the shortcode.
     */
    add_filter('cn_locate_file_paths', array($template, 'templatePaths'));
    cnShortcode::addFilterRegistry('cn_locate_file_paths');
    do_action('cn_template_include_once-' . $template->getSlug());
    do_action('cn_template_enqueue_js-' . $template->getSlug());
    /*
     * Set the query vars and run query.
     */
    // Show only public or private [if permitted] entries.
    if (is_user_logged_in() || $atts['private_override'] != FALSE) {
        $visibilityfilter = " AND (visibility='private' OR visibility='public') AND (" . $atts['list_type'] . " != '')";
    } else {
        $visibilityfilter = " AND (visibility='public') AND (`" . $atts['list_type'] . "` != '')";
    }
    // Get the current date from WP which should have the current time zone offset.
    $wpCurrentDate = date('Y-m-d', $connections->options->wpCurrentTime);
    // Whether or not to include the event occurring today or not.
    $atts['include_today'] ? $includeToday = '<=' : ($includeToday = '<');
    $newSQL = "SELECT * FROM " . CN_ENTRY_TABLE . " WHERE" . "  (YEAR(DATE_ADD('{$wpCurrentDate}', INTERVAL " . $atts['days'] . " DAY))" . " - YEAR(DATE_ADD(FROM_UNIXTIME(`" . $atts['list_type'] . "`), INTERVAL " . $connections->options->sqlTimeOffset . " SECOND)) )" . " - ( MID(DATE_ADD('{$wpCurrentDate}', INTERVAL " . $atts['days'] . " DAY),5,6)" . " < MID(DATE_ADD(FROM_UNIXTIME(`" . $atts['list_type'] . "`), INTERVAL " . $connections->options->sqlTimeOffset . " SECOND),5,6) )" . " > ( YEAR('{$wpCurrentDate}')" . " - YEAR(DATE_ADD(FROM_UNIXTIME(`" . $atts['list_type'] . "`), INTERVAL " . $connections->options->sqlTimeOffset . " SECOND)) )" . " - ( MID('{$wpCurrentDate}',5,6)" . " " . $includeToday . " MID(DATE_ADD(FROM_UNIXTIME(`" . $atts['list_type'] . "`), INTERVAL " . $connections->options->sqlTimeOffset . " SECOND),5,6) )" . $visibilityfilter;
    //$out .= print_r($newSQL , TRUE);
    $results = $wpdb->get_results($newSQL);
    //$out .= print_r($results , TRUE);
    // If there are no results no need to proceed and output message.
    if (empty($results)) {
        $noResultMessage = __('No results.', 'connections');
        $noResultMessage = apply_filters('cn_upcoming_no_result_message', $noResultMessage);
        $out .= '<p class="cn-upcoming-no-results">' . $noResultMessage . '</p>';
    } else {
        /*The SQL returns an array sorted by the birthday and/or anniversary date. However the year end wrap needs to be accounted for.
        		Otherwise earlier months of the year show before the later months in the year. Example Jan before Dec. The desired output is to show
        		Dec then Jan dates.  This function checks to see if the month is a month earlier than the current month. If it is the year is changed to the following year rather than the current.
        		After a new list is built, it is resorted based on the date.*/
        foreach ($results as $key => $row) {
            if (gmmktime(23, 59, 59, gmdate('m', $row->{$atts['list_type']}), gmdate('d', $row->{$atts['list_type']}), gmdate('Y', $connections->options->wpCurrentTime)) < $connections->options->wpCurrentTime) {
                $dateSort[] = $row->{$atts['list_type']} = gmmktime(0, 0, 0, gmdate('m', $row->{$atts['list_type']}), gmdate('d', $row->{$atts['list_type']}), gmdate('Y', $connections->options->wpCurrentTime) + 1);
            } else {
                $dateSort[] = $row->{$atts['list_type']} = gmmktime(0, 0, 0, gmdate('m', $row->{$atts['list_type']}), gmdate('d', $row->{$atts['list_type']}), gmdate('Y', $connections->options->wpCurrentTime));
            }
        }
        array_multisort($dateSort, SORT_ASC, $results);
        if (empty($atts['list_title'])) {
            switch ($atts['list_type']) {
                case 'birthday':
                    if ($atts['days'] >= 1) {
                        $list_title = 'Upcoming Birthdays the next ' . $atts['days'] . ' days';
                    } else {
                        $list_title = 'Today\'s Birthdays';
                    }
                    break;
                case 'anniversary':
                    if ($atts['days'] >= 1) {
                        $list_title = 'Upcoming Anniversaries the next ' . $atts['days'] . ' days';
                    } else {
                        $list_title = 'Today\'s Anniversaries';
                    }
                    break;
            }
        } else {
            $list_title = $atts['list_title'];
        }
        ob_start();
        // Prints the template's CSS file.
        do_action('cn_template_inline_css-' . $template->getSlug(), $atts);
        $out .= ob_get_contents();
        ob_end_clean();
        $out .= '<div class="connections-list cn-upcoming cn-' . $atts['list_type'] . '" id="cn-list" data-connections-version="' . $connections->options->getVersion() . '-' . $connections->options->getDBVersion() . '">' . "\n";
        $out .= "\n" . '<div class="cn-template cn-' . $template->getSlug() . '" id="cn-' . $template->getSlug() . '">' . "\n";
        $out .= "\n" . '<div class="cn-clear" id="cn-list-head">' . "\n";
        if ($atts['show_title']) {
            $out .= '<div class="cn-upcoming-title">' . $list_title . '</div>';
        }
        $out .= "\n" . '</div>' . "\n";
        $out .= '<div class="cn-clear" id="cn-list-body">' . "\n";
        foreach ($results as $row) {
            $entry = new cnvCard($row);
            $vCard =& $entry;
            // Configure the page where the entry link to.
            $entry->directoryHome(array('page_id' => $atts['home_id'], 'force_home' => $atts['force_home']));
            if (!$atts['show_lastname']) {
                $entry->setLastName('');
            }
            $entry->name = $entry->getName(array('format' => $atts['name_format']));
            $alternate == '' ? $alternate = '-alternate' : ($alternate = '');
            $out .= '<div class="cn-upcoming-row' . $alternate . ' vcard ' . '">' . "\n";
            ob_start();
            do_action('cn_action_card-' . $template->getSlug(), $entry, $template, $atts);
            $out .= ob_get_contents();
            ob_end_clean();
            $out .= '</div>' . "\n";
        }
        $out .= "\n" . '</div>' . "\n";
        $out .= "\n" . '<div class="cn-clear" id="cn-list-foot">' . "\n";
        $out .= "\n" . '</div>' . "\n";
        $out .= "\n" . '</div>' . "\n";
        $out .= "\n" . '</div>' . "\n";
    }
    if (cnSettingsAPI::get('connections', 'connections_compatibility', 'strip_rnt')) {
        $search = array("\r\n", "\r", "\n", "\t");
        $replace = array('', '', '', '');
        $out = str_replace($search, $replace, $out);
    }
    // Clear any filters that have been added.
    // This allows support using the shortcode multiple times on the same page.
    cnShortcode::clearFilterRegistry();
    return $out;
}