Example #1
0
 /**
  * Compile LESS to CSS, appending data from styles and parsing urls
  * @param  string $less_output    LESS code
  * @param  string $dirname        absolute path where compiled file will be saved (to parse URLs correctly)
  * @param  array  $data           style data
  * @param  string $prepend_prefix prefix to prepend all selectors (for widget mode)
  * @param  string $area Area (C/A) to get setting for
  * @return string CSS code
  */
 public function customCompile($less_output, $dirname, $data = array(), $prepend_prefix = '', $area = AREA)
 {
     // Apply all Custom styles styles
     $less_output .= Styles::factory(fn_get_theme_path('[theme]', $area))->getLess($data);
     // Inject Bootstrap fluid variables
     $less_output .= self::getLayoutStyleVariables();
     if (!empty($prepend_prefix)) {
         $less_output = $prepend_prefix . " {\n" . $less_output . "\n}";
     }
     $output = $this->parse($less_output);
     // Remove "body" definition
     if (!empty($prepend_prefix)) {
         $output = str_replace($prepend_prefix . ' body', $prepend_prefix, $output);
     }
     return Less::parseUrls($output, $dirname, fn_get_theme_path('[themes]/[theme]/media'));
 }
Example #2
0
 /**
  * Compile LESS to CSS, appending data from styles and parsing urls
  * @param  string $less_output    LESS code
  * @param  string $dirname        absolute path where compiled file will be saved (to parse URLs correctly)
  * @param  array  $data           style data
  * @param  string $prepend_prefix prefix to prepend all selectors (for widget mode)
  * @param  string $area           current working area
  * @return string CSS code
  */
 public function customCompile($less_output, $dirname, $data = array(), $prepend_prefix = '', $area = AREA)
 {
     // Apply all Custom styles styles
     if ($area == 'C') {
         $less_output .= "\n" . Styles::factory(fn_get_theme_path('[theme]', $area))->getLess($data);
         // Inject Bootstrap fluid variables
         $less_output .= self::getLayoutStyleVariables();
     }
     if (!empty($prepend_prefix)) {
         $less_output = $prepend_prefix . " {\n" . $less_output . "\n}";
     }
     if (false) {
         // is not implemented completely
         $output = self::parseWithNodeJs($less_output, $area);
     } else {
         $output = !empty($less_output) ? $this->parse($less_output) : '';
     }
     // Remove "body" definition
     if (!empty($prepend_prefix)) {
         $output = str_replace($prepend_prefix . ' body', $prepend_prefix, $output);
     }
     return Less::parseUrls($output, $dirname, fn_get_theme_path('[themes]/[theme]/media', $area));
 }
Example #3
0
 /**
  * Gets style LESS code
  * @param  array  $current_style style data to override current style data
  * @return string style LESS code
  */
 public function getLess($current_style = array())
 {
     $custom_less = '';
     $style = $this->get(Registry::get('runtime.layout.style_id'));
     if (!empty($style['less'])) {
         $custom_less = $style['less'];
         $custom_less .= "\n" . $style['custom_css'];
     }
     if (!empty($current_style)) {
         $custom_less .= Less::arrayToLessVars($current_style);
     }
     return $custom_less;
 }
Example #4
0
            $css_content = '';
        }
        $data = array();
        // FIXME: Bacward preset compatibility
        if (!empty($_REQUEST['preset_id'])) {
            $_REQUEST['style_id'] = $_REQUEST['preset_id'];
        }
        // If theme ID passed, set default theme
        if (!empty($_REQUEST['style_id'])) {
            fn_theme_editor_set_style($_REQUEST['style_id']);
            // If theme elements passed, get them
        } elseif (!empty($_REQUEST['style']['data'])) {
            $data = $_REQUEST['style']['data'];
            $data = Styles::factory($theme_name)->processCopy('', $data);
        }
        $less = new Less();
        $import_path[] = Registry::get('config.dir.root') . fn_get_theme_path('/[relative]/[theme]/css');
        $import_path[] = Registry::get('config.dir.root') . fn_get_theme_path('/[relative]/[theme]/css/tygh');
        $less->setImportDir($import_path);
        $content = $css_content . $less->customCompile($less_content, Registry::get('config.dir.root'), $data);
        // remove external fonts to avoid flickering when styles are reloaded
        //$content = preg_replace("/@font-face \{.*?\}/s", '', $content);
    }
    header('content-type: text/css');
    fn_echo($content);
    exit;
} elseif ($mode == 'duplicate') {
    // FIXME: Bacward preset compatibility
    if (!empty($_REQUEST['preset_id'])) {
        $_REQUEST['style_id'] = $_REQUEST['preset_id'];
    }
Example #5
0
/**
 * Merges css and less files
 *
 * @param array $files Array with style files
 * @param string $styles Style code
 * @param string $prepend_prefix Prepend prefix
 * @param array $params additional params
 */
function fn_merge_styles($files, $styles = '', $prepend_prefix = '', $params = array(), $area = AREA)
{
    $prefix = !empty($prepend_prefix) ? 'embedded' : 'standalone';
    $make_rtl = false;
    if (fn_is_rtl_language()) {
        $prefix .= '-rtl';
        $make_rtl = true;
    }
    $output = '';
    $less_output = '';
    $less_reflection = array();
    $compiled_less = '';
    $compiled_css = '';
    $relative_path = fn_get_theme_path('[relative]/[theme]/css', $area);
    $hashes = array();
    $names = array_map(function ($v) {
        return !empty($v['relative']) ? $v['relative'] : false;
    }, $files);
    // Check file changes
    if (Development::isEnabled('compile_check') || Debugger::isActive()) {
        $dir_root = Registry::get('config.dir.root');
        foreach ($names as $index => $name) {
            if (file_exists($dir_root . '/' . $name)) {
                $hashes[] = $name . filemtime($dir_root . '/' . $name);
            }
        }
    }
    $hashes[] = md5(implode('|', $names));
    $hashes[] = md5($styles);
    if ($area == 'C') {
        $hashes[] = Registry::get('runtime.layout.layout_id');
        $hashes[] = Registry::get('runtime.layout.style_id');
    }
    arsort($hashes);
    $hash = md5(implode(',', $hashes) . PRODUCT_VERSION) . fn_get_storage_data('cache_id');
    $filename = $prefix . '.' . $hash . '.css';
    $theme_manifest = Themes::factory(fn_get_theme_path('[theme]', 'C'))->getManifest();
    if (!Storage::instance('assets')->isExist($relative_path . '/' . $filename)) {
        Debugger::checkpoint('Before styles compilation');
        foreach ($files as $src) {
            $m_prefix = '';
            $m_suffix = '';
            if (!empty($src['media'])) {
                $m_prefix = "\n@media " . $src['media'] . " {\n";
                $m_suffix = "\n}\n";
            }
            if (strpos($src['file'], '.css') !== false) {
                $output .= "\n" . $m_prefix . fn_get_contents($src['file']) . $m_suffix;
            } elseif ($area != 'C' || empty($theme_manifest['converted_to_css'])) {
                $less_output_chunk = '';
                if (file_exists($src['file'])) {
                    if ($area == 'C' && (empty($theme_manifest['parent_theme']) || $theme_manifest['parent_theme'] == 'basic')) {
                        $less_output_chunk = "\n" . $m_prefix . fn_get_contents($src['file']) . $m_suffix;
                    } else {
                        $less_output_chunk = "\n" . $m_prefix . '@import "' . str_replace($relative_path . '/', '', $src['relative']) . '";' . $m_suffix;
                    }
                }
                if (!empty($params['reflect_less'])) {
                    if (preg_match('{/addons/([^/]+)/}is', $src['relative'], $m)) {
                        $less_reflection['output']['addons'][$m[1]] .= $less_output_chunk;
                    } else {
                        $less_reflection['output']['main'] .= $less_output_chunk;
                    }
                }
                $less_output .= $less_output_chunk;
            }
        }
        $header = str_replace('[files]', implode("\n", $names), Registry::get('config.js_css_cache_msg'));
        if (!empty($styles)) {
            $less_output .= $styles;
        }
        // Prepend all styles with prefix
        if (!empty($prepend_prefix)) {
            $less_output = $output . "\n" . $less_output;
            $output = '';
        }
        if (!empty($output)) {
            $compiled_css = Less::parseUrls($output, Storage::instance('assets')->getAbsolutePath($relative_path), fn_get_theme_path('[themes]/[theme]/media', $area));
        }
        if (!empty($theme_manifest['converted_to_css']) && $area == 'C') {
            $theme_css_path = fn_get_theme_path('[themes]/[theme]', $area) . '/css';
            $pcl_filepath = $theme_css_path . '/' . Themes::$compiled_less_filename;
            if (file_exists($pcl_filepath)) {
                $compiled_css .= fn_get_contents($pcl_filepath);
            }
            list($installed_addons) = fn_get_addons(array('type' => 'active'));
            foreach ($installed_addons as $addon) {
                $addon_pcl_filpath = $theme_css_path . "/addons/{$addon['addon']}/" . Themes::$compiled_less_filename;
                if (file_exists($pcl_filepath)) {
                    $compiled_css .= fn_get_contents($addon_pcl_filpath);
                }
            }
        }
        if (!empty($less_output)) {
            $less = new Less();
            if (!empty($params['compressed'])) {
                $less->setFormatter('compressed');
            }
            $less->setImportDir($relative_path);
            try {
                $compiled_less = $less->customCompile($less_output, Storage::instance('assets')->getAbsolutePath($relative_path), array(), $prepend_prefix, $area);
            } catch (Exception $e) {
                $skip_save = true;
                $shift = 4;
                $message = '<div style="border: 2px solid red; padding: 5px;">LESS ' . $e->getMessage();
                if (preg_match("/line: (\\d+)/", $message, $m)) {
                    $lo = explode("\n", $less_output);
                    $message .= '<br /><br /><pre>' . implode("\n", array_splice($lo, intval($m[1]) - $shift, $shift * 2)) . '</pre>';
                }
                $message .= '</div>';
                fn_set_notification('E', __('error'), $message);
            }
        }
        if (empty($skip_save)) {
            $compiled_content = $compiled_css . "\n" . $compiled_less;
            // Move all @import links to the Top of the file.
            if (preg_match_all('/@import url.*?;/', $compiled_content, $imports)) {
                $compiled_content = preg_replace('/@import url.*?;/', '', $compiled_content);
                foreach ($imports[0] as $import_link) {
                    $compiled_content = $import_link . "\n" . $compiled_content;
                }
            }
            if ($make_rtl) {
                $compiled_content = \CSSJanus::transform($compiled_content);
                $compiled_content = "body {\ndirection: rtl;\n}\n" . $compiled_content;
            }
            Storage::instance('assets')->put($relative_path . '/' . $filename, array('contents' => $header . $compiled_content, 'compress' => false, 'caching' => true));
            if (!empty($params['use_scheme'])) {
                fn_put_contents(fn_get_cache_path(false) . 'theme_editor/' . $filename, $output . '#LESS#' . $less_output);
            }
            if (!empty($params['reflect_less'])) {
                $less_reflection['import_dirs'] = array($relative_path);
                fn_put_contents(fn_get_cache_path(false) . 'less_reflection.json', json_encode($less_reflection));
            }
        }
        Debugger::checkpoint('After styles compilation');
    }
    $url = Storage::instance('assets')->getUrl($relative_path . '/' . $filename);
    return $url;
}
Example #6
0
 public static function convertPresets401To402()
 {
     $theme_name = Registry::get('config.base_theme');
     $schema_path = fn_get_theme_path('[themes]/' . $theme_name . '/styles/schema.json', 'C');
     $schema = file_get_contents($schema_path);
     if (!empty($schema)) {
         $schema = json_decode($schema, true);
     }
     db_query('ALTER TABLE ?:bm_layouts CHANGE `preset_id` `preset_id` varchar(64) NOT NULL default ""');
     $presets = db_get_array('SELECT * FROM ?:theme_presets');
     foreach ($presets as $preset) {
         $preset['name'] = self::_formPresetName($preset['name']);
         //We should rename default preset to satori in order to prevent default preset creation.
         if ($preset['name'] == 'default') {
             $preset['name'] = 'satori';
         }
         db_query('UPDATE ?:bm_layouts SET preset_id = ?s WHERE preset_id = ?i', $preset['name'], $preset['preset_id']);
         $preset_path = fn_get_theme_path('[themes]/' . $theme_name . '/styles/data/', 'C');
         if (file_exists($preset_path . $preset['name'] . '.less')) {
             continue;
         }
         $preset_data = unserialize($preset['data']);
         $less = array();
         foreach ($preset_data as $section => $fields) {
             foreach ($fields as $field_id => $value) {
                 switch ($section) {
                     case 'general':
                         $less[$field_id] = empty($value) ? $schema[$section]['fields'][$field_id]['off'] : $schema[$section]['fields'][$field_id]['on'];
                         break;
                     case 'colors':
                         $less[$field_id] = $value;
                         break;
                     case 'fonts':
                         $less[$field_id] = $value['family'];
                         if (!empty($value['size'])) {
                             $field_name = $schema[$section]['fields'][$field_id]['properties']['size']['match'];
                             $field_value = $value['size'] . $schema[$section]['fields'][$field_id]['properties']['size']['unit'];
                             $less[$field_name] = $field_value;
                         }
                         if (!empty($value['style'])) {
                             foreach ($value['style'] as $style_type => $style_value) {
                                 $field_name = $schema[$section]['fields'][$field_id]['properties']['style'][$style_type]['match'];
                                 $field_value = $schema[$section]['fields'][$field_id]['properties']['style'][$style_type]['property'];
                                 $less[$field_name] = $field_value;
                             }
                         }
                         break;
                     case 'backgrounds':
                         $value['transparent'] = isset($value['transparent']) ? $value['transparent'] : false;
                         $value['full_width'] = isset($value['full_width']) ? $value['full_width'] : false;
                         foreach ($value as $bg_name => $bg_value) {
                             switch ($bg_name) {
                                 case 'color':
                                     $field_name = $schema[$section]['fields'][$field_id]['properties']['color']['match'];
                                     $less[$field_name] = $bg_value;
                                     break;
                                 case 'gradient':
                                     $field_name = $schema[$section]['fields'][$field_id]['gradient']['match'];
                                     $less[$field_name] = $bg_value;
                                     break;
                                 case 'image_data':
                                     $less[$schema[$section]['fields'][$field_id]['properties']['pattern']] = !empty($bg_value) ? 'url("' . $bg_value . '")' : 'transparent';
                                     break;
                                 case 'repeat':
                                     $field_name = $schema[$section]['fields'][$field_id]['properties']['repeat'];
                                     if (!empty($field_name)) {
                                         $less[$field_name] = $bg_value;
                                     }
                                     break;
                                 case 'attachment':
                                     $field_name = $schema[$section]['fields'][$field_id]['properties']['attachment'];
                                     if (!empty($field_name)) {
                                         $less[$field_name] = $bg_value;
                                     }
                                     break;
                                 case 'full_width':
                                     if (!isset($schema[$section]['fields'][$field_id]['copies'])) {
                                         break;
                                     }
                                     foreach ($schema[$section]['fields'][$field_id]['copies']['full_width'] as $copies) {
                                         if (!empty($value['full_width'])) {
                                             if (!empty($copies['inverse'])) {
                                                 $less[$copies['match']] = $copies['default'];
                                             } elseif (isset($less[$copies['source']])) {
                                                 $less[$copies['match']] = $less[$copies['source']];
                                             }
                                         } else {
                                             if (empty($copies['inverse'])) {
                                                 $less[$copies['match']] = $copies['default'];
                                             }
                                         }
                                     }
                                     break;
                                 case 'transparent':
                                     if (!isset($schema[$section]['fields'][$field_id]['copies'])) {
                                         break;
                                     }
                                     foreach ($schema[$section]['fields'][$field_id]['copies']['transparent'] as $copies) {
                                         if (!empty($value['transparent'])) {
                                             if (!empty($copies['inverse'])) {
                                                 $less[$copies['match']] = $copies['default'];
                                             } elseif (isset($less[$copies['source']])) {
                                                 $less[$copies['match']] = $less[$copies['source']];
                                             }
                                         } else {
                                             if (empty($copies['inverse'])) {
                                                 $less[$copies['match']] = $copies['default'];
                                             }
                                         }
                                     }
                                     break;
                                 case 'image_name':
                                     break;
                                 default:
                                     fn_print_r('Unprocessed background property: ' . $bg_name);
                             }
                         }
                         break;
                     default:
                         fn_print_r('Error: Section ' . $section . ' was not processed');
                 }
             }
         }
         $less = Less::arrayToLessVars($less);
         file_put_contents(fn_get_theme_path('[themes]/' . $theme_name . '/styles/data/' . $preset['name'] . '.less', 'C'), $less);
     }
     db_query('DROP TABLE IF EXISTS ?:theme_presets');
     return true;
 }