Controls
1 month ago
Tabs
1 month ago
CTF_Db.php
1 month ago
CTF_Feed_Builder.php
1 month ago
CTF_Feed_Saver.php
1 month ago
CTF_Feed_Saver_Manager.php
1 month ago
CTF_Post_Set.php
1 month ago
CTF_Theme_CSS.php
1 month ago
CTF_Tooltip_Wizard.php
1 month ago
SB_Builder_Customizer.php
1 month ago
CTF_Theme_CSS.php
254 lines
| 1 | <?php |
| 2 | /** |
| 3 | * class CTF_Theme_CSS |
| 4 | */ |
| 5 | |
| 6 | namespace TwitterFeed\Builder; |
| 7 | |
| 8 | |
| 9 | class CTF_Theme_CSS { |
| 10 | |
| 11 | const WRAP_SELECTOR = '.ctf-preview-ctn'; |
| 12 | |
| 13 | /** |
| 14 | * @var string |
| 15 | */ |
| 16 | var $file; |
| 17 | |
| 18 | /** |
| 19 | * @var string |
| 20 | */ |
| 21 | var $css; |
| 22 | |
| 23 | /** |
| 24 | * @var array |
| 25 | */ |
| 26 | var $parsed; |
| 27 | |
| 28 | /** |
| 29 | * @var array |
| 30 | */ |
| 31 | var $styles; |
| 32 | |
| 33 | public function __construct( $file ) { |
| 34 | $this->file = $file; |
| 35 | } |
| 36 | |
| 37 | /** |
| 38 | * Whether or not a cache exists for this stylesheet. Updates daily or when the theme's stylesheet changes |
| 39 | * |
| 40 | * @return bool |
| 41 | * |
| 42 | * @since 2.0 |
| 43 | */ |
| 44 | public function is_cached() { |
| 45 | $stored_styles = get_option( 'ctf_theme_styles', array( 'file' => '', 'last_checked' => 0, 'styles' => array() ) ); |
| 46 | |
| 47 | if ( empty( $stored_styles['file'] ) |
| 48 | || $stored_styles['file'] !== $this->file ) { |
| 49 | return false; |
| 50 | } |
| 51 | |
| 52 | if ( empty( $stored_styles['last_checked'] ) |
| 53 | || $stored_styles['last_checked'] < (time() - DAY_IN_SECONDS) ) { |
| 54 | return false; |
| 55 | } |
| 56 | |
| 57 | $this->styles = $stored_styles['styles']; |
| 58 | |
| 59 | return true; |
| 60 | } |
| 61 | |
| 62 | /** |
| 63 | * Stores the styles in a wp_option |
| 64 | * |
| 65 | * @return bool |
| 66 | * |
| 67 | * @since 2.0 |
| 68 | */ |
| 69 | public function cache() { |
| 70 | $stored_styles = get_option( 'ctf_theme_styles', array( 'file' => '', 'last_checked' => 0, 'styles' => array() ) ); |
| 71 | |
| 72 | $stored_styles['file'] = $this->file; |
| 73 | $stored_styles['styles'] = $this->styles; |
| 74 | $stored_styles['last_checked'] = time(); |
| 75 | |
| 76 | return update_option( 'ctf_theme_styles', $stored_styles, false ); |
| 77 | } |
| 78 | |
| 79 | /** |
| 80 | * @return array |
| 81 | * |
| 82 | * @since 2.0 |
| 83 | */ |
| 84 | public function get_styles() { |
| 85 | return $this->styles; |
| 86 | } |
| 87 | |
| 88 | /** |
| 89 | * Makes an HTTP request to get the contents of the stylesheet |
| 90 | * |
| 91 | * @since 2.0 |
| 92 | */ |
| 93 | public function load_css() { |
| 94 | $url = $this->file; |
| 95 | $args = array( |
| 96 | 'timeout' => 60, |
| 97 | 'sslverify' => false |
| 98 | ); |
| 99 | $response = wp_remote_get( esc_url_raw( $url ), $args ); |
| 100 | |
| 101 | if ( ! is_wp_error( $response ) ) { |
| 102 | // certain ways of representing the html for double quotes causes errors so replaced here. |
| 103 | $this->css = $response['body']; |
| 104 | } else { |
| 105 | $this->css = false; |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | /** |
| 110 | * Uses a regex to detect selectors and styles and coverts them to key => value pairs |
| 111 | * |
| 112 | * @return bool |
| 113 | * |
| 114 | * @since 2.0 |
| 115 | */ |
| 116 | public function parse() { |
| 117 | if ( empty( $this->css ) ) { |
| 118 | return false; |
| 119 | } |
| 120 | $css = $this->css; |
| 121 | preg_match_all( '/(?ims)([a-z0-9\s\.\:#_\-@,]+)\{([^\}]*)\}/', $css, $arr); |
| 122 | $result = array(); |
| 123 | foreach ( $arr[0] as $i => $x ){ |
| 124 | $selector = trim( $arr[1][ $i ] ); |
| 125 | $rules = explode( ';', trim( $arr[2][ $i ] ) ); |
| 126 | $rules_arr = array(); |
| 127 | foreach ( $rules as $strRule ) { |
| 128 | if ( !empty( $strRule ) ) { |
| 129 | $rule = explode( ":", $strRule ); |
| 130 | $rule_0 = isset( $rule[0] ) ? $rule[0] : 'null'; |
| 131 | $rule_1 = isset( $rule[1] ) ? $rule[1] : ''; |
| 132 | $rules_arr[ trim($rule_0) ] = trim( $rule_1 ); |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | $selectors = explode(',', trim( $selector ) ); |
| 137 | foreach ( $selectors as $strSel ) { |
| 138 | if ( ! isset( $result[ $strSel ] ) ) { |
| 139 | $result[ $strSel ] = $rules_arr; |
| 140 | } else { |
| 141 | $result[ $strSel . '_2' ] = $rules_arr; |
| 142 | } |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | $this->parsed = $result; |
| 147 | } |
| 148 | |
| 149 | /** |
| 150 | * Looks for styles based on specified selectors that are used |
| 151 | * in generating the style HTML |
| 152 | * |
| 153 | * @return array |
| 154 | * |
| 155 | * @since 2.0 |
| 156 | */ |
| 157 | public function find_styles() { |
| 158 | if ( empty( $this->css ) ) { |
| 159 | return array(); |
| 160 | } |
| 161 | foreach ( $this->parsed as $selector => $property_array ) { |
| 162 | foreach ( $property_array as $property => $style ) { |
| 163 | $this->process( $selector, $property, $style ); |
| 164 | } |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | /** |
| 169 | * Loop through all selectors and see if they can be used in our generated |
| 170 | * style HTML |
| 171 | * |
| 172 | * @param string $selector |
| 173 | * @param string $property |
| 174 | * @param string $style |
| 175 | * |
| 176 | * @since 2.0 |
| 177 | */ |
| 178 | public function process( $selector, $property, $style ) { |
| 179 | $selector = trim( $selector ); |
| 180 | if ( $selector === 'body' ) { |
| 181 | if ( in_array( $property, array( 'color', 'background-color', 'background', 'font-size' ), true ) ) { |
| 182 | if ( ! isset( $this->styles[ $selector ]['properties'][ $property ]['style'] ) ) { |
| 183 | $this->styles[ $selector ]['properties'][ $property ]['style'] = $style; |
| 184 | } |
| 185 | } |
| 186 | } elseif ( $selector === 'a' ) { |
| 187 | |
| 188 | if ( in_array( $property, array( 'color', 'font-weight', 'text-decoration' ), true ) ) { |
| 189 | if ( ! isset( $this->styles[ $selector ]['properties'][ $property ]['style'] ) ) { |
| 190 | $this->styles[ $selector ]['properties'][ $property ]['style'] = $style; |
| 191 | } |
| 192 | } |
| 193 | } elseif ( $selector === 'a:hover' ) { |
| 194 | if ( in_array( $property, array( 'color', 'font-weight', 'text-decoration' ), true ) ) { |
| 195 | if ( ! isset( $this->styles[ $selector ]['properties'][ $property ]['style'] ) ) { |
| 196 | $this->styles[ $selector ]['properties'][ $property ]['style'] = $style; |
| 197 | } |
| 198 | } |
| 199 | } elseif ( $selector === 'p' ) { |
| 200 | if ( in_array( $property, array( 'color', 'font-weight', 'font-size' ), true ) ) { |
| 201 | if ( ! isset( $this->styles[ $selector ]['properties'][ $property ]['style'] ) ) { |
| 202 | $this->styles[ $selector ]['properties'][ $property ]['style'] = $style; |
| 203 | } |
| 204 | } |
| 205 | } elseif ( $selector === 'h3' ) { |
| 206 | if ( in_array( $property, array( 'color', 'font-weight', 'font-size' ), true ) ) { |
| 207 | if ( ! isset( $this->styles[ $selector ]['properties'][ $property ]['style'] ) ) { |
| 208 | $this->styles[ $selector ]['properties'][ $property ]['style'] = $style; |
| 209 | } |
| 210 | } |
| 211 | } elseif ( $selector === '.entry-content' ) { |
| 212 | if ( in_array( $property, array( 'color', 'font-size' ), true ) ) { |
| 213 | if ( ! isset( $this->styles[ $selector ]['properties'][ $property ]['style'] ) ) { |
| 214 | $this->styles[ $selector ]['properties'][ $property ]['style'] = $style; |
| 215 | } |
| 216 | } |
| 217 | } elseif ( $selector === '.entry-content a' ) { |
| 218 | if ( in_array( $property, array( 'color', 'font-weight', 'text-decoration' ), true ) ) { |
| 219 | if ( ! isset( $this->styles[ $selector ]['properties'][ $property ]['style'] ) ) { |
| 220 | $this->styles[ $selector ]['properties'][ $property ]['style'] = $style; |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | /** |
| 227 | * Creates the actual style HTML as a string |
| 228 | * |
| 229 | * @return string |
| 230 | * |
| 231 | * @since 2.0 |
| 232 | */ |
| 233 | public function generate_style_html() { |
| 234 | if ( empty( $this->styles ) ) { |
| 235 | return ''; |
| 236 | } |
| 237 | |
| 238 | $wrap_selector = self::WRAP_SELECTOR; |
| 239 | $html = '<style id="sb-customizer-preview-styles">' . "\n"; |
| 240 | foreach ( $this->styles as $selector => $data ) { |
| 241 | $selector = $selector === 'body' ? $wrap_selector : $wrap_selector . ' ' . $selector; |
| 242 | $html .= $selector . '{' . "\n"; |
| 243 | foreach ( $data as $property_data => $values ) { |
| 244 | foreach ( $values as $property_key => $property_values ) { |
| 245 | $html .= ' ' . $property_key . ': ' . $property_values['style'] . ';' . "\n"; |
| 246 | } |
| 247 | } |
| 248 | $html .= '}' . "\n"; |
| 249 | } |
| 250 | $html .= '</style>'; |
| 251 | |
| 252 | return $html; |
| 253 | } |
| 254 | } |