<?php
// GENERIC PLUGIN STATIC METHODS
class gg_static {
    
    
    // To be used instead of wp_verify_nonce() to properly sanitize the value
    public static function verify_nonce($str, $key) {
        return (wp_verify_nonce(sanitize_text_field(wp_unslash($str)), $key)) ? true : false;   
    }
    
    
    
    
    // creating an escaping function similar to wp_kses_post but allowing <style> and <script>
    public static function wp_kses_ext($content) {
        if(empty($content)) {
            return $content;   
        }
        
        $allowed_tags = wp_kses_allowed_html('post');

        $allowed_tags['style'] = array(
            'type' => array()
        );
        $allowed_tags['script'] = array(
            'type' => array(),
            'src'  => array(),
            'async' => array(),
            'defer' => array(),
        );

        $allowed_tags['form'] = array(
            'action' => array(),
            'method' => array(),
            'enctype' => array(),
            'disabled' => array(),
            'readonly' => array(),
        );
        $allowed_tags['input'] = array(
            'type' => array(),
            'name' => array(),
            'value' => array(),
            'placeholder' => array(),
            'checked' => array(),
            'disabled' => array(),
            'autocomplete'=> array(),
            'readonly' => array(),
            'size' => array(),
        );
        $allowed_tags['select'] = array(
            'name' => array(),
            'multiple' => array(),
            'autocomplete'=> array(),
            'readonly' => array(),
            'size' => array(),
        );
        $allowed_tags['option'] = array(
            'value' => array(),
            'selected' => array(),
            'disabled' => array(),
        );
        $allowed_tags['textarea'] = array(
            'name' => array(),
            'placeholder' => array(),
            'rows' => array(),
            'cols' => array(),
            'autocomplete'=> array(),
            'readonly' => array(),
            'size' => array(),
            'disabled' => array(),
        );
        $allowed_tags['button'] = array(
            'type' => array(),
            'name' => array(),
            'value' => array(),
            'autocomplete'=> array(),
            'size' => array(),
            'disabled' => array(),
        );
        $allowed_tags['label'] = array(
            'for' => array(),
        );

        foreach ($allowed_tags as $tag => $attributes) {
            $allowed_tags[$tag]['class'] = array();
            $allowed_tags[$tag]['id'] = array();
            $allowed_tags[$tag]['data-*'] = true;
        }
        
        
        $sanitized = wp_kses(
            htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), 
            $allowed_tags
        );
        return htmlspecialchars_decode($sanitized, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401);
    }
    
    
    
    
    // trying to understand whether a local image URL is fetchable to create thumbnails
    public static function url_is_fetchable($url) {
        if(is_integer($url)) {
            return true;   
        }
        if(isset($GLOBALS['gg_url_is_fetchable'])) {
            return $GLOBALS['gg_url_is_fetchable'];
        }
        
        // not for external URLs
        $home_url = home_url(); 
        $site_domain = parse_url($home_url, PHP_URL_HOST);
        $target_domain = parse_url($url, PHP_URL_HOST);

        if($site_domain !== $target_domain) {
            $to_return = true;
        }
        else {
            // perform
            $response = wp_remote_get($url);
            if(is_wp_error($response)) {
                $to_return = false;
            }
            else {
                $status_code = wp_remote_retrieve_response_code($response);
                if($status_code === 200) {
                    $to_return = true;
                }
                elseif($status_code === 401 || $status_code === 403) {
                    $to_return = false;
                }
            }
        }
        
        $GLOBALS['gg_url_is_fetchable'] = $to_return;
        return $to_return;
    }
    
    
    

    // WP image ID to path
    public static function img_id_to_path($img_src) {
        if(is_numeric($img_src)) {
            if(get_option('gg_use_url_for_wp_thumbs', true)) {
                return self::img_id_to_url($img_src);
            }
            
            $max_img_size   = get_option('gg_fetched_img_max_size', 'max');
            $wp_img_data    = wp_get_attachment_metadata((int)$img_src);
            $upload_dirs    = wp_upload_dir();
            
            if($max_img_size == 'max') {
                if(is_array($wp_img_data) && isset($wp_img_data['file'])) { 
                    $img_src = $upload_dirs['basedir'] . '/' . $wp_img_data['file'];
                }
                else {
                    $url = self::img_id_to_url($img_src);
                    if($url != $img_src) {
                        $img_src = str_replace($upload_dirs['baseurl'], $upload_dirs['basedir'], $url);
                    }
                }
            }
            
            else {
                $url = self::img_id_to_url($img_src);
                if($url != $img_src) {
                    $img_src = str_replace($upload_dirs['baseurl'], $upload_dirs['basedir'], $url);
                }
            }
        }

        return $img_src;
    }

    

    // WP image ID to url
    public static function img_id_to_url($img_src) {
        $orig_img_src = $img_src;
        
        if(is_numeric($img_src)) {
            $max_img_size   = get_option('gg_fetched_img_max_size', 'max');
            $wp_img_data    = wp_get_attachment_metadata((int)$img_src);
            
            if($max_img_size == 'max') {
                if($wp_img_data && isset($wp_img_data['file'])) {
                    $upload_dirs = wp_upload_dir();
                    $img_src = $upload_dirs['baseurl'] . '/' . $wp_img_data['file'];
                }
                else {
                    $result = wp_get_attachment_image_url($img_src, 'full');
                    if($result) {
                        $img_src = $result;
                    }
                }
            }
            else {
                $size = ($max_img_size == 'big') ? 'large' : 'medium_large';
                $result = wp_get_attachment_image_url($img_src, $size);
                
                if(!$result) {
                    $result = wp_get_attachment_image_url($img_src, 'full');
                }
                
                if($result) {
                    $img_src = $result;
                }
            }
        }
        
        
        // be sure URL is fetchable, otherwise go back to path
        if(get_option('gg_use_url_for_wp_thumbs') && !self::url_is_fetchable($img_src)) {
            update_option('gg_use_url_for_wp_thumbs', 0, false);
            return self::img_id_to_path($orig_img_src);
        }
        
        return $img_src;
    }

    

    // thumbnail source switch between timthumb and ewpt
    public static function thumb_src($img_id, $width = false, $height = false, $quality = 80, $alignment = 'c', $resize = 1, $canvas_col = 'FFFFFF', $fx = array()) {
        if(!$img_id) {
            return false;
        }

        if(get_option('gg_use_timthumb') || isset($_REQUEST['gg_thumb_creation_debug'])) {
            $img_path = self::img_id_to_path($img_id);
            $ext = pathinfo($img_path, PATHINFO_EXTENSION);
            
            // be sure Timthumb can handle it
            if(in_array(strtolower($ext), array('jpg', 'jpeg', 'png', 'gif'))) {
                return GG_TT_URL .'?src='. $img_path .'&w='. (int)$width .'&h='. (int)$height .'&a='.$alignment.'&q='.$quality.'&zc='.$resize.'&cc='.$canvas_col;   
            }
        }
        
        $params = array(
            'w'		=> $width,
            'h'		=> $height,
            'q' 	=> $quality,
            'a'		=> $alignment,
            'cc'    => $canvas_col,
            'fx'	=> $fx,
            'rs'	=> $resize,
            'get_url_if_not_cached' => (get_option('gg_no_async_ewpt')) ? false : GG_EWPT_URL,
        );
        return easy_wp_thumb($img_id, $params);
    }
    
    
    
    // thumbnail source switch between timthumb and ewpt and WP image where available - use the remote URL version 
    public static function inline_thumb_src($img_id, $width = false, $height = false, $quality = 80, $alignment = 'c', $resize = 1, $canvas_col = 'FFFFFF', $fx = array()) {
        if(!$img_id) {
            return false;
        }

        // wordpress images on admin side - use WP thumbs
        if(is_admin() && is_integer($img_id)) {
            return wp_get_attachment_image_src($img_id, array($width, $height))[0];
        }
        return self::thumb_src($img_id, $width, $height, $quality, $alignment, $resize, $canvas_col, $fx);
    }
    
    
    
    // slider's image srcset value comoposer (handling image ID and the full-res image)
    public static function slider_srcset_val($img_id, $thumb_center, $slider_w, $slider_h) {
        $thumb_quality = (int)get_option('gg_thumb_q', 90);
        
        $fixed_h = false;
        if(strpos($slider_h, 'px') !== false) {
            $fixed_h = (int)str_replace('px', '', $slider_h);   
        }
        
        $max_w = (int)get_option('gg_masonry_basewidth', 1400);
        if(strpos($slider_w, 'px') !== false) {
            $max_w = (int)str_replace('px', '', $slider_w);   
        }
        elseif(strpos($slider_w, '%') !== false) {
            $max_w = ceil($max_w  * ((int)str_replace('px', '', $slider_w) / 100));
        }
        
        
        $sizes = array(
            self::inline_thumb_src($img_id, $max_w, $fixed_h, $thumb_quality, $thumb_center) .' '. (int)get_option('gg_masonry_basewidth', 1400) .'w'
        );
        if($max_w > 850) {
            $sizes[] = self::inline_thumb_src($img_id, 768, $fixed_h, $thumb_quality, $thumb_center) .' 768w';
        }
        
        return implode(', ', $sizes);
    }
    
    
    
    // given the gallery type - return the image path ready to be used
    public static function img_src_on_type($raw_src, $type) {
        if(get_option('gg_use_url_for_wp_thumbs', true)) {
            return self::img_url_on_type($raw_src, $type);
        }
        
        
        if(in_array($type, array('wp', 'wp_cat', 'wp_gall', 'cpt_tax', 'rml'))) {
            $img_full_src = self::img_id_to_path($raw_src);	
        } 
        elseif($type == 'gg_album') {
            include_once(GG_DIR .'/classes/gg_local_images.php');
            $fm = new gg_local_images();
            
            $img_full_src = trailingslashit(get_option('gg_albums_basepath', $fm->suggested_path)) . $raw_src;	
        }
        elseif($type == 'ngg') {
            $img_full_src = (strpos($raw_src, WP_CONTENT_DIR) === false) ? WP_CONTENT_DIR.'/'.$raw_src : $raw_src;	
        }
        else {
            $img_full_src = $raw_src;
        }	

        return str_replace(' ', '%20', $img_full_src);
    }



    // given the gallery type - return the image url ready to be used
    public static function img_url_on_type($raw_src, $type) {

        if(in_array($type, array('wp', 'wp_cat', 'wp_gall', 'rml'))) {
            $img_url = self::img_id_to_url($raw_src);
        } 
        elseif($type == 'gg_album') {
            include_once(GG_DIR .'/classes/gg_local_images.php');
            $fm = new gg_local_images();

            $img_url = trailingslashit(get_option('gg_albums_baseurl', $fm->suggested_url)) . $raw_src;	
        }
        elseif($type == 'ngg') {
            if(strpos($raw_src, WP_CONTENT_DIR) !== false) {$img_url = str_replace(WP_CONTENT_DIR.'/', '', $raw_src);} // fix old error in path calculation
            else {$img_url = $raw_src;}

            if(strpos($img_url, 'wp-content/') !== false) {$img_url = str_replace('wp-content/', '', $img_url);} // fix old error in path calculation
            else {$img_url = $raw_src;}

            $img_url = (strpos($img_url, WP_CONTENT_URL) === false) ? WP_CONTENT_URL.'/'.$img_url : $img_url;
        }
        else {
            $img_url = $raw_src;
        }	

        return str_replace(' ', '%20', $img_url);
    }
    
    
    
    // Given a local image path, eventually returns IPTC data as associative array (title, descr, author, tags)
    public static function maybe_get_iptc_tags($img_path) {
        
        $path_arr  = explode('/', $img_path);
        $file_name = end($path_arr);
        
        $to_return = array(
            'title'  => self::stringToFilename($file_name), 
            'descr'  => '',
            'author' => '',	
            'tags'   => '',
        );

        try {
            include_once(GG_DIR .'/classes/iptc.php');
            $iptc = new Iptc($img_path);
            
            if(get_option('gga_img_title_src') == 'iptc' && !empty($iptc->fetch('005'))) {
                $to_return['title'] = $iptc->fetch('005');    
            }
            
            if(!empty($iptc->fetch('120'))) {
                $to_return['descr'] = $iptc->fetch('120');     
            }
            
            if(!empty($iptc->fetch('080'))) {
                $to_return['author'] = $iptc->fetch('080');     
            }
            if(empty($to_return['author']) && !empty($iptc->fetch('116'))) {
                $to_return['author'] = $iptc->fetch('116');
            }
            
            //var_dump($iptc->fetch('025'));
            
            if(is_array($iptc->fetch('025')) && count($iptc->fetch('025'))) {
                $to_return['tags'] = implode(',', $iptc->fetch('025')); 
            }
        }
        catch(Exception $e) {}
        
        return $to_return;
    }
    
    
    
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    
    
    // watermarker
    public static function watermark_image($img_src) {
        include_once(GG_DIR . '/classes/lc_wp_watermarker.php');
        @ini_set('memory_limit', '512M');


        // cached instance? use it!
        if(isset($GLOBALS['gg_wm_instance'])) {
            $lcww = $GLOBALS['gg_wm_instance'];	
        }
        else {

            // retrieve watermark image
            $wm_img = get_option('gg_watermark_img');
            if(!filter_var($wm_img, FILTER_VALIDATE_URL)) {
                wp_die( esc_html__("Watermark image's url is wrong", 'gg_ml') );	
            }

            // use the path to be quicker and more compatible
            $attachment_id = attachment_url_to_postid($wm_img);
            if($attachment_id) {
                $wm_img = get_attached_file($attachment_id); // full filesystem path
            }
            
            // setup class
            $wp_dirs = wp_upload_dir();
            $folder_name = 'gg_watermarked'; 

            $args = array(
                'cache_folder_dir' => trailingslashit($wp_dirs['basedir']) . $folder_name,
                'cache_folder_url' => trailingslashit($wp_dirs['baseurl']) . $folder_name,

                'quality' 		=> 95,
                'proportional' 	=> get_option('gg_wm_proport', false),
                'prop_sizes'	=> get_option('gg_wm_prop_val', array(15, 15)),
                'wm_pos'		=> strtolower(get_option('gg_watermark_pos', 'mm')),
                'wm_margin'		=> get_option('gg_wm_margin', 10),
                'wm_margin_type'=> get_option('gg_wm_margin_type', '%'),
                'wm_opacity'	=> get_option('gg_watermark_opacity', 1),
            );

            $lcww = new lc_wp_watermark($wm_img, $args, get_option('gg_use_url_for_wp_thumbs', true));
            $GLOBALS['gg_wm_instance'] = $lcww;	
        }

        return $lcww->mark_it($img_src);
    }
    
    
    
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    
    
    public static function getPrefixedCss($css,$prefix) {
        # Wipe all block comments
        $css = preg_replace('!/\*.*?\*/!s', '', $css);

        $parts = explode('}', $css);
        $keyframeStarted = false;
        $mediaQueryStarted = false;

        foreach($parts as &$part) {
            $part = trim($part); # Wht not trim immediately .. ?
            if(empty($part)) {
                $keyframeStarted = false;
                continue;
            }
            else { # This else is also required
                $partDetails = explode('{', $part);

                if (strpos($part, 'keyframes') !== false) {
                    $keyframeStarted = true;
                    continue;
                }

                if($keyframeStarted) {
                    continue;
                }

                if(substr_count($part, "{")==2) {
                    $mediaQuery = $partDetails[0]."{";
                    $partDetails[0] = $partDetails[1];
                    $mediaQueryStarted = true;
                }

                $subParts = explode(',', $partDetails[0]);
                foreach($subParts as &$subPart) {
                    if(trim($subPart)==="@font-face") continue;
                    else $subPart = $prefix . ' ' . trim($subPart);
                }

                if(substr_count($part,"{")==2) {
                    $part = $mediaQuery."\n".implode(', ', $subParts)."{".$partDetails[2];
                }
                elseif(empty($part[0]) && $mediaQueryStarted) {
                    $mediaQueryStarted = false;
                    $part = implode(', ', $subParts)."{".$partDetails[2]."}\n"; //finish media query
                }
                else {
                    if(isset($partDetails[1]))
                    {   # Sometimes, without this check,
                        # there is an error-notice, we don't need that..
                        $part = implode(', ', $subParts)."{".$partDetails[1];
                    }
                }

                unset($partDetails, $mediaQuery, $subParts); # Kill those three ..
            }   unset($part); # Kill this one as well
        }

        # Finish with the whole new prefixed string/file in one line
        return(preg_replace('/\s+/',' ',implode("} ", $parts)));
    }



    // handles custom CSS written in LESS and returns a CSS string
    public static function custom_css_less_parser() {
        ob_start();
        include_once(GG_DIR.'/frontend_css.php');

        $css = ob_get_clean();
        if(!trim($css)) { 
            return '';    
        }

        // Divi fix
        if(class_exists('DiviExtension')) {
            $css .= self::getPrefixedCss($css, '#et-boc .et-l');
        }

        return $css;
    }



    /* 
     * Create the frontend CSS
     * @param (bool) $skip_if_file_exists - true to not act if customm CSS file already exists
     */
    public static function create_frontend_css($skip_if_file_exists = false) {	
        global $wp_filesystem;
        $filepath = GG_DIR .'/css/custom.css';
        
        if(empty($wp_filesystem)) {
            require_once(ABSPATH .'/wp-admin/includes/file.php');
            WP_Filesystem();
        }

        
        $versioning_key = 'gg_dynamic_css_versioning';
        $versioning = array(
            'gg' => GG_VER
        );
        $versioning = apply_filters($versioning_key, $versioning);
        ksort($versioning);
        
        
        if($skip_if_file_exists && $wp_filesystem->exists($filepath) && md5(json_encode($versioning)) == get_option($versioning_key)) {
            return true;   
        }
        
        $css = self::custom_css_less_parser();
        if(trim($css)) {
            
            $versioning_pre = array();
            foreach($versioning as $subj => $ver) {
                $versioning_pre[] = $subj .' > '.$ver;   
            }
            $versioning_pre = '/* '. implode(' | ', $versioning_pre) .' */
';
            
            if(!$wp_filesystem->put_contents($filepath, $versioning_pre.$css)) {
                update_option('gg_force_inline_css', 1, false);
                $error = true;
            }
            else {
                update_option($versioning_key, md5(json_encode($versioning)), false);
                update_option('gg_dynamic_scripts_id', md5($css));	
            }
        }
        else {
            if($wp_filesystem->exists($filepath))	{
                wp_delete_file($filepath);
            }
        }

        return (isset($error)) ? false : true;
    }
    
    
    
    /* Be sure... well read the function name */
    public static function be_sure_dynamic_css_exists() {
        if(!get_option('gg_force_inline_css')) {
            self::create_frontend_css(true);
        }
    }
     
    
    
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    
    
    // preloader code
    public static function preloader() {
        return '
        <div class="gg_loader">
            <div class="ggl_1"></div>
            <div class="ggl_2"></div>
            <div class="ggl_3"></div>
            <div class="ggl_4"></div>
        </div>';	
    }
    
    
    
    // given images total number - returns a randomized indexes array
    public static function random_img_indexes($img_count) {
        $arr = array();
        for($a = 0; $a < $img_count; $a++) {
            $arr[] = $a;	
        }

        shuffle($arr);
        return $arr;
    }
    
    
    
    // get the current URL
    public static function curr_url() {
        $pageURL = 'http';

        if((isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") || (function_exists('is_ssl') && is_ssl())) {
            $pageURL .= "s";
        }
        
        $host = (isset($_SERVER['HTTP_HOST'])) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : ''; 
        $uri = (isset($_SERVER["REQUEST_URI"])) ? filter_var(wp_unslash($_SERVER["REQUEST_URI"]), FILTER_SANITIZE_URL) : ''; 
        
        $pageURL .= "://" . $host . $uri;
        return $pageURL;
    }
	


    // get file extension from a filename
    public static function stringToExt($string) {
        // remove url parameters
        if(strpos($string, '?') !== false) {
            $arr = explode('?', $string);
            $string = $arr[0];	
        }

        $pos = strrpos($string, '.');
        $ext = strtolower(substr($string,$pos));
        return $ext;	
    }



    // get filename without extension
    public static function stringToFilename($string, $raw_name = false) {
        $pos = strrpos($string, '.');
        $name = substr($string, 0, $pos);
        
        if(!$raw_name) {
            $name = ucwords(str_replace('_', ' ', $name));
        }
        return $name;	
    }



    // know if server supports cURL followlocation command
    public static function use_followlocation() {
        return (!ini_get('open_basedir') && !ini_get('safe_mode')) ? true : false; 	
    }
    
    
    
    // bytes to human readable format
    public static function human_filesize($bytes, $decimals = 2) {
        $size = array('Bytes','KB','MB','GB','TB','PB','EB','ZB','YB');
        $factor = floor((strlen($bytes) - 1) / 3);

        $val = sprintf("%.{$decimals}f", $bytes / pow(1024, $factor));

        // remove precise values
        if($decimals) {
            if(!(int)substr($val, ($decimals * -1))) {
                $arr = explode('.', $val);
                $val = $arr[0];
            }
        }

        return $val .' '. $size[$factor];
    }
    
    
    
    // retrieve term meta value considering the old WP option storing system - automatically moves data to the new storing system
    public static function retrocomp_get_term_meta($term_id, $meta_key, $old_key, $default_val = false) {
        $val = get_term_meta($term_id, $meta_key, true);
       
        if($val === false) {
            $val = get_option($old_key, $default_val);
            delete_option($old_key);
            update_term_meta($term_id, $meta_key, $val); 
        }
        
        return $val;
    }
    
    
    
    // FontAwesome v4 class retrocompatibility
    public static function fontawesome_v4_retrocomp($class) {
        if(!empty($class) && strpos($class, ' ') === false) {
            $class = 'fas '. $class;    
        }
        
        return $class;
    }
    
    
    
    // returning "selected" string if a targeted builder layout is active in cookies (cols or rows)
    public static function builder_layout_selected($target_layout) {
        $default        = 'cols';
        $cookie_name    = 'gg_builder_layout';
        $cookie_val     = (!isset($_COOKIE[$cookie_name ])) ? $default : $_COOKIE[$cookie_name ];
        
        return ($target_layout == $cookie_val) ? 'selected' : '';
    }
    
    
    
    // link field generator
    public static function link_field($src, $val = '') {
        if($src == 'page') {
            $code = '<select name="gg_item_link[]" class="gg_link_field gg_lc_select_dd" autocomplete="off">';

            foreach(get_pages() as $pag) {
                $code .= '<option value="'.$pag->ID.'" '. selected($val, $pag->ID, false) .'>'.$pag->post_title.'</option>';
            }

            return $code . '</select>';
        }
        else if($src == 'custom') {
            return '<input type="text" name="gg_item_link[]" value="'. esc_attr($val) .'" class="gg_link_field" placeholder="'. esc_attr__('insert a valid link', 'gg_ml') .'" autocomplete="off" />';
        }
        else {
            return '<input type="hidden" name="gg_item_link[]" value="" autocomplete="off" />';
        }
    }
    
    
    
    // given a field value (eg. gallery builder sidebox) sanitizes it to be empty or a number
    public static function empty_or_number_val($val) {
        return ($val === '' || $val === false) ? '' : (int)$val;       
    }
    
    
    
    // clean emoticons from instagram texts
    public static function clean_emoticons($text) {
        $clean_text = "";

        // Match Emoticons
        $regexEmoticons = '/[\x{1F600}-\x{1F64F}]/u';
        $clean_text = preg_replace($regexEmoticons, '', $text);

        // Match Miscellaneous Symbols and Pictographs
        $regexSymbols = '/[\x{1F300}-\x{1F5FF}]/u';
        $clean_text = preg_replace($regexSymbols, '', $clean_text);

        // Match Transport And Map Symbols
        $regexTransport = '/[\x{1F680}-\x{1F6FF}]/u';
        $clean_text = preg_replace($regexTransport, '', $clean_text);

        return $clean_text;
    }
    

    
    // Converting RGB(A) color to HEX
    public static function rgba2hex($rgba) {
        if(strpos($rgba, '#') === 0) {
            return $rgba;
        }

        preg_match('/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i', $rgba, $by_color);
        return sprintf('#%02x%02x%02x', $by_color[1], $by_color[2], $by_color[3]);
    }
    
    
    
    // hex color to RGBA
    public static function hex2rgba($hex, $alpha) {
        if(substr(strtolower($hex), 0, 3) == 'rgb' || substr(strtolower($hex), 0, 4) == 'rgba') {
            return self::hex2rgba(self::rgba2hex($hex), $alpha);
        }
        
        // if is RGB or transparent - return it
        $three_chars_pattern = '/^#[a-f0-9]{3}$/i';
        $six_chars_pattern = '/^#[a-f0-9]{6}$/i';
        
        if(empty($hex) || $hex == 'transparent' || (!preg_match($three_chars_pattern, $hex) && !preg_match($six_chars_pattern, $hex))) {
            return $hex;
        }

        $hex = str_replace("#", "", $hex);
        if(strlen($hex) == 3) {
            $r = hexdec(substr($hex,0,1).substr($hex,0,1));
            $g = hexdec(substr($hex,1,1).substr($hex,1,1));
            $b = hexdec(substr($hex,2,1).substr($hex,2,1));
        } else {
            $r = hexdec(substr($hex,0,2));
            $g = hexdec(substr($hex,2,2));
            $b = hexdec(substr($hex,4,2));
        }
        $rgb = array($r, $g, $b);
        $rgb = 'rgb('. implode(",", $rgb) .')';

        $rgba = str_replace(array('rgb', ')'), array('rgba', ', '.$alpha.')'), $rgb);
        return $rgba;	
    }
    
}
