Source: flipcss.phps - download
<?php
/* 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * flipcss.php 0.9.2
 * by Daif Alazmi (http://daif.net)
 * daif@daif.net
 * 
 * Link:
 *  http://daif.net/flipcss/flipcss.phps
 * 
 * Description:
 *  This Tool flip CSS rules direction from LTR to RTL or vice versa .
 *  tool support these CSS rules: float, text-align, padding, margin
 *  and border-radius .
 * 
 * Syntax:
 *  right to left
 *  $flip = new FlipCSS();
 *  $rtl_css = $flip->parseCSS($css_data, 'RTL', array('.pull-right', '.pull-left'));
 *  left to right
 *  $flip = new FlipCSS();
 *  $ltr_css = $flip->parseCSS($css_data, 'LTR', array('.pull-right', '.pull-left'));
 * 
 * Changelog
 * 0.1    first release
 * 0.2    rewrite padding and margin
 * 0.3    support border-radius
 * 0.4    added GPL License
 * 0.5    support border
 * 0.6    fix issue with rewrite padding,margin,border Regex
 * 0.7    added the $escaped parameter
 * 0.8    some code improvement
 * 0.9    fix parsing issue with two braces like @media , @-*
 * 0.9.1  ignore escape array it is count zero. 
 * 0.9.2  fix parsing left and right if not start with spaces.
*/



class FlipCSS{
    
/**
     * version number
     *
     * @var string
     */
    
public $version '0.9.2';

    
/**
     * CSS content
     *
     * @var string
     */
    
public $css_data;

    
/**
     * flipped CSS content
     *
     * @var string
     */
    
public $css_flipped;
    
/**
     * CSS ignored class name
     *
     * @var array
     */
    
public $escaped = array('.pull-right','.pull-left','.text-left','.text-right','.left','.right');

    
/**
     * Parse the CSS data
     *
     * @param   string
     * @param   string
     * @param   array
     * @return  string
     */
    
public function parseCSS($css_data$dir='RTL'$escaped=array()) {
        
$this->css_data     =   $css_data;
        
//set Generated by message
        
$this->css_flipped  "/* Generated by flipcss.php ".$this->version.
                                
" (http://flipcss.com/) */\nbody{\n  direction:$dir;\n}\n\n";
        
// remove comments
        
$this->css_data     preg_replace('/\*\//',"*/\n" ,$this->css_data);
        
$this->css_data     preg_replace('/\/\*(.*)?\*\//Usi','' ,$this->css_data);
        
//remove @charset
        
$this->css_data     preg_replace('/@charset .+;/Ui',""$this->css_data);
        
// try to unminify minified css
        
$this->css_data     preg_replace('/{/'," {\n"$this->css_data);
        
$this->css_data     preg_replace('/}/',"\n}\n"$this->css_data);
        
$this->css_data     preg_replace('/;/',";\n"$this->css_data);
        
$this->css_data     preg_replace('/,/',",\n"$this->css_data);
        
// rewrite padding,margin,border
        
$this->css_data     =   preg_replace('/(\h*)(padding|margin|border)\h*:\h*(\d+.*)\h+(\d+.*)\h+(\d+.*)\h+(\d+.*)\h*;/Ui'
                                    
"\\1\\2-right:\\4;\n\\1\\2-left:\\6;\n" ,$this->css_data);
        
// rewrite border-radius 
        
$this->css_data     preg_replace('/(\h*|)border-radius:(.+)\h+(.+)\h+(.+)\h+(.+)\h*;/Ui',"\\1border-top-left-radius:\\2;\\1border-top-".
                    
"right-radius:\\3;\\1border-bottom-right-radius:\\4;\\1border-bottom-left-radius:\\5;"$this->css_data);
        
// start parsing css file
        // find all class name
        
preg_match_all('/((@(media).+{.+{.+}\s+})|(((?!@(m|-)).)+{.+}))/Uis'$this->css_data$css_arr);
        
// prepare regex
        
$regex trim(trim(implode('|'array_map('preg_quote'$escaped))), '|');
        
//foreach the result array 
        
foreach($css_arr[0] as $css_key=>$css_val) {
            if(
preg_match('/@(m|-)(.+){(.+})\s+}/Uis'$css_arr[0][$css_key], $media_arr)) {
                
$css_prefix "@".$media_arr[1].$media_arr[2]." {\n";
                
$css_inner  '';
                
preg_match_all('/(.+){(.+)}/Uis'$media_arr[3], $css_rules);
                foreach(
$css_rules[0] as $sub_key=>$sub_val) {
                    
//ignore escaped classes
                    
if(!$regex || ($regex && !preg_match('/('.$regex.')/i'$css_rules[1][$sub_key]))) {
                        if(
$rules $this->parseCSSRules($css_rules[2][$sub_key])) {
                            
$css_inner .= $css_rules[1][$sub_key]." {\n";
                            
$css_inner .= "    ".str_replace(";\n"";\n    ",trim($rules))."\n";
                            
$css_inner .= "  }\n";
                        }
                    }
                }
                
$css_suffix "}\n";
            } else {
                
preg_match_all('/(.+){(.+)}/Uis'$css_arr[0][$css_key], $css_rules);
                
$css_prefix '';
                
$css_inner  '';
                foreach(
$css_rules[0] as $sub_key=>$sub_val) {
                    
//ignore escaped classes
                    
if(!$regex || ($regex && !preg_match('/('.$regex.')/i'$css_rules[1][$sub_key]))) {
                        if(
$rules $this->parseCSSRules($css_rules[2][$sub_key])) {
                            
$css_inner .= $css_rules[1][$sub_key]." {\n";
                            
$css_inner .= "  ".str_replace(";\n"";\n  ",trim($rules))."\n";
                            
$css_inner .= "}\n";
                        }
                    }
                }
                
$css_suffix "";
            }
            if(
$css_inner) {
                
$this->css_flipped .= $css_prefix $css_inner $css_suffix;
                
$this->css_flipped  preg_replace('/({|})\n\n/Ui',"\\1\n"$this->css_flipped);
                
$this->css_flipped  preg_replace('/\s\s{/Ui'," {"$this->css_flipped);
                
$this->css_flipped  preg_replace('/(\v)\v+/',"\\1"$this->css_flipped);
            }
        }
        return (
$this->css_flipped);
    }

    
/**
     * Parse and flip the CSS data
     *
     * @param   string
     * @return  string
     */
    
public function parseCSSRules($rules) {
        
$return         '';
        
$rules_arr      explode(";"$rules);
        foreach(
$rules_arr as $rule) {
            
//ignore rules that doesn't need flipping
            
if(preg_match('/(left|right)/i'$rule)) {
                
//flip float
                
if(preg_match('/float\h*:\h*(.+)/i'$rule$rule_arr)) {
                    
$rule    'float: '.((trim($rule_arr[1])=='left')?'right':'left');
                    
$return .= trim($rule).";\n";
                
                
//flip text-align
                
} elseif(preg_match('/text-align\h*:\h*(.+)/i'$rule$rule_arr)) {
                    
$rule    'text-align: '.((trim($rule_arr[1])=='left')?'right':'left');
                    
$return .= trim($rule).";\n";
                
                
//flip padding, margin, border
                
} elseif(preg_match('/(\*|)(margin|padding|border)-(left|right)\h*:\h*(.+)/i'$rule$rule_arr)) {
                    
$dir = ((trim($rule_arr[3])=='left')?'right':'left');
                    
//reset direction rule
                    
if((trim($rule_arr[3]) == 'left' && !preg_match('/'.trim($rule_arr[2]).'\-right/i'$rules)) || (trim($rule_arr[2]) == 'right' && !preg_match('/'.trim($rule_arr[2]).'\-left/i'$rules))) {
                        
$rule trim($rule_arr[1]).trim($rule_arr[2]).'-'.$rule_arr[3].": 0;\n";
                    } else {
                        
$rule '';
                    }
                    
$rule   .= trim($rule_arr[1]).trim($rule_arr[2]).'-'.$dir.': '.$rule_arr[4];
                    
$return .= trim($rule).";\n";
                
                
//flip border-radius
                
} elseif(preg_match('/border-(top|bottom)-(left|right)-radius\h*:\h*(.+)/i'$rule$rule_arr)) {
                    
$dir = ((trim($rule_arr[2])=='left')?'right':'left');
                    
//reset direction rule
                    
if((trim($rule_arr[2]) == 'left' && !preg_match('/'.trim($rule_arr[1]).'\-right/i'$rules)) || (trim($rule_arr[2]) == 'right' && !preg_match('/'.trim($rule_arr[1]).'\-left/i'$rules))) {
                        
$rule 'border-'.$rule_arr[1].'-'.$rule_arr[2].'-radius: 0;'."\n";
                    } else {
                        
$rule '';
                    }
                    
//write new direction rule
                    
$rule   .= 'border-'.$rule_arr[1].'-'.$dir.'-radius: '.$rule_arr[3];
                    
$return .= trim($rule).";\n";
                
                
//flip left, right
                
} elseif(preg_match('/\h*(left|right)\h*:\h*(.+)/i'$rule$rule_arr)) {
                    
$dir = ((trim($rule_arr[1])=='left')?'right':'left');
                    
//reset LTR rule
                    
if((trim($rule_arr[1]) == 'left' && !preg_match('/\h+right\h*:/i'$rules)) || (trim($rule_arr[1]) == 'right' && !preg_match('/\h+left\h*:/i'$rules))) {
                        
$rule trim($rule_arr[1]).": auto;\n";
                    } else {
                        
$rule '';
                    }
                    
$rule   .= $dir.': '.$rule_arr[2];
                    
$return .= trim($rule).";\n";
                }
            }
        }
        return(
$return);
    }
}   
?>