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
     if (!empty($from_default_layout) && !empty($layout_id)) {
         $repo_dest = fn_get_theme_path('[themes]/' . $from_default_layout['theme_name'], 'C');
         $layout_path = fn_normalize_path($repo_dest . '/layouts/' . $from_default_layout['filename']);
         $exim = Exim::instance(Registry::get('runtime.company_id'), $layout_id, fn_get_theme_path('[theme]', 'C'));
         $structure = $exim->getStructure($layout_path);
         if (!empty($structure)) {
             foreach ($layout_data as $key => $val) {
                 if (!empty($structure->layout->{$key})) {
                     $structure->layout->{$key} = $val;
                 }
             }
             if (!isset($layout_data['is_default'])) {
                 $structure->layout->is_default = 0;
             }
             $exim->import($structure, array('import_style' => 'update'));
             fn_create_theme_logos_by_layout_id($layout_data['theme_name'], $layout_id, Registry::get('runtime.company_id'), false, Styles::factory($layout_data['theme_name'])->getDefault());
         }
     }
     fn_clear_cache('assets', 'design/');
     return array(CONTROLLER_STATUS_OK, fn_url('block_manager.manage?s_layout=' . $layout_id));
 }
 if ($mode == 'update_block') {
     $description = array();
     if (!empty($_REQUEST['block_data']['description'])) {
         $_REQUEST['block_data']['description']['lang_code'] = DESCR_SL;
         $description = $_REQUEST['block_data']['description'];
     }
     if (!empty($_REQUEST['block_data']['content_data'])) {
         $_REQUEST['block_data']['content_data']['lang_code'] = DESCR_SL;
         if (isset($_REQUEST['block_data']['content'])) {
             $_REQUEST['block_data']['content_data']['content'] = $_REQUEST['block_data']['content'];
Example #4
0
function fn_theme_editor($params, $lang_code = CART_LANGUAGE)
{
    $view = Tygh::$app['view'];
    $theme_name = Registry::get('runtime.layout.theme_name');
    $layout_id = Registry::get('runtime.layout.layout_id');
    if (!Registry::get('runtime.layout.style_id')) {
        $default_style_id = Styles::factory($theme_name)->getDefault();
        db_query('UPDATE ?:bm_layouts SET style_id = ?s WHERE layout_id = ?i', $default_style_id, $layout_id);
        Registry::set('runtime.layout.style_id', $default_style_id);
    }
    $style_id = Registry::get('runtime.layout.style_id');
    // Backward presets compatibility
    Registry::set('runtime.layout.preset_id', $style_id);
    // get current style
    $current_style = Styles::factory($theme_name)->get($style_id, array('parse' => true));
    // get all styles
    $styles_list = Styles::factory($theme_name)->getList();
    $schema = Styles::factory($theme_name)->getSchema();
    $sections = array('te_general' => 'theme_editor.general', 'te_logos' => 'theme_editor.logos', 'te_colors' => 'theme_editor.colors', 'te_fonts' => 'theme_editor.fonts', 'te_backgrounds' => 'theme_editor.backgrounds', 'te_css' => 'theme_editor.css');
    foreach ($sections as $section_id => $section) {
        if ($section_id == 'te_logos') {
            // Logos is hardcoded section, no need to define it in schema
            continue;
        }
        $section_id = str_replace('te_', '', $section_id);
        if (!isset($schema[$section_id])) {
            unset($sections['te_' . $section_id]);
        }
    }
    if (empty($params['selected_section']) || !isset($sections[$params['selected_section']])) {
        reset($sections);
        $params['selected_section'] = key($sections);
    }
    $theme = Themes::factory($theme_name);
    $theme_manifest = $theme->getManifest();
    if (!empty($theme_manifest['converted_to_css'])) {
        if (empty($params['selected_css_file'])) {
            $params['selected_css_file'] = Themes::$compiled_less_filename;
        }
        $view->assign('selected_css_file', $params['selected_css_file']);
        $view->assign('css_files_list', $theme->getCssFilesList());
        $view->assign('css_content', $theme->getCssContents($params['selected_css_file']));
    }
    $view->assign('cse_logo_types', fn_get_logo_types());
    $view->assign('cse_logos', fn_get_logos(Registry::get('runtime.company_id')));
    $view->assign('selected_section', $params['selected_section']);
    $view->assign('te_sections', $sections);
    $view->assign('current_style', $current_style);
    $view->assign('props_schema', $schema);
    $view->assign('theme_patterns', Patterns::instance()->get($style_id));
    $view->assign('styles_list', $styles_list);
    // FIXME: Backward compatibility
    $view->assign('presets_list', $styles_list);
    $view->assign('current_preset', $current_style);
    $view->assign('manifest', Styles::factory($theme_name)->getManifest());
    $view->assign('theme_manifest', $theme_manifest);
    $view->assign('layouts', Layout::instance()->getList(array('theme_name' => $theme_name)));
    $view->assign('layout_data', Layout::instance()->get($layout_id));
    $view->assign('theme_url', fn_url(empty($params['theme_url']) ? '' : $params['theme_url']));
}
Example #5
0
 /**
  * Updates or creates layout
  * @param  array $layout_data layout data
  * @param  int   $layout_id   layout ID to update, zero to create
  * @return int   ID of updated/created layout
  */
 public function update($layout_data, $layout_id = 0)
 {
     if (fn_allowed_for('ULTIMATE')) {
         if (empty($layout_data['company_id'])) {
             $layout_data['company_id'] = $this->_company_id;
         }
     }
     $theme_name = empty($layout_data['theme_name']) ? fn_get_theme_path('[theme]', 'C', $this->_company_id, false) : $layout_data['theme_name'];
     $available_styles = Styles::factory($theme_name)->getList(array('short_info' => true));
     if (empty($layout_id)) {
         if (!empty($layout_data['from_layout_id'])) {
             $layout_data['style_id'] = Styles::factory($theme_name)->getStyle($layout_data['from_layout_id']);
         }
         if (!empty($layout_data['style_id']) && !isset($available_styles[$layout_data['style_id']])) {
             unset($layout_data['style_id']);
         }
         if (empty($layout_data['style_id'])) {
             $layout_data['style_id'] = Styles::factory($theme_name)->getDefault();
         }
         $layout_id = db_query("INSERT INTO ?:bm_layouts ?e", $layout_data);
         // Create logos
         $types = fn_get_logo_types();
         foreach ($types as $type => $data) {
             if (!empty($data['for_layout'])) {
                 $object_ids[$type] = fn_create_logo(array('type' => $type, 'layout_id' => $layout_id), !empty($layout_data['company_id']) ? $layout_data['company_id'] : 0);
             }
         }
     } else {
         if (isset($layout_data['style_id']) && !isset($available_styles[$layout_data['style_id']])) {
             $layout_data['style_id'] = Styles::factory($theme_name)->getDefault();
         }
         db_query("UPDATE ?:bm_layouts SET ?u WHERE layout_id = ?i", $layout_data, $layout_id);
     }
     if (!empty($layout_data['is_default'])) {
         $this->setDefault($layout_id);
     }
     if (!empty($layout_data['from_layout_id'])) {
         $this->copyById($layout_data['from_layout_id'], $layout_id);
     }
     return $layout_id;
 }
Example #6
0
     }
     Tygh::$app['view']->assign('logo_types', fn_get_logo_types(true));
 }
 $restored_company_data = fn_restore_post_data('company_data');
 if (!empty($restored_company_data) && $mode == 'add') {
     if (!empty($restored_company_data['shippings'])) {
         $restored_company_data['shippings'] = implode(',', $restored_company_data['shippings']);
     }
     $company_data = fn_array_merge($company_data, $restored_company_data);
 }
 if (fn_allowed_for('ULTIMATE')) {
     if ($mode == 'update') {
         $available_themes = fn_get_available_themes(fn_get_theme_path('[theme]', 'C', $company_id));
         $theme_name = fn_get_theme_path('[theme]', 'C', $company_id);
         $layout = Layout::instance($company_id)->getDefault($theme_name);
         $style = Styles::factory($theme_name)->get($layout['style_id']);
         Tygh::$app['view']->assign('current_style', $style);
         Tygh::$app['view']->assign('theme_info', $available_themes['current']);
     }
     $countries_list = fn_get_simple_countries();
     if (!empty($company_data['countries_list'])) {
         if (!is_array($company_data['countries_list'])) {
             $company_countries = explode(',', $company_data['countries_list']);
         } else {
             $company_countries = $company_data['countries_list'];
         }
         $_countries = array();
         foreach ($company_countries as $code) {
             if (isset($countries_list[$code])) {
                 $_countries[$code] = $countries_list[$code];
                 unset($countries_list[$code]);
Example #7
0
/**
 * Gets all available themes: from repo and installed one
 * @param string $theme_name current theme
 * @return type
 */
function fn_get_available_themes($theme_name)
{
    $default_theme = Registry::get('config.base_theme');
    $repo_path = fn_get_theme_path('[repo]', 'C');
    $rel_repo_path = str_replace(Registry::get('config.dir.root'), '', $repo_path);
    $installed_path = fn_get_theme_path('[themes]', 'C');
    $rel_installed_path = fn_get_theme_path('/[relative]', 'C');
    $themes = array('repo' => fn_get_dir_contents($repo_path, true), 'installed' => fn_get_dir_contents($installed_path, true));
    sort($themes['repo']);
    sort($themes['installed']);
    $themes_list = array();
    foreach ($themes as $type => $_themes) {
        foreach ($_themes as $v) {
            // FIXME: Forbid to install the basic theme but continue to support it
            if ($type == 'repo' && $v == 'basic') {
                continue;
            }
            $dir = $type == 'repo' ? $repo_path : $installed_path;
            $rel_dir = $type == 'repo' ? $rel_repo_path : $rel_installed_path;
            if (file_exists($dir . '/' . $v . '/' . THEME_MANIFEST)) {
                $manifest_content = fn_get_contents($dir . '/' . $v . '/' . THEME_MANIFEST);
                $themes_list[$type][$v] = json_decode($manifest_content, true);
            } elseif (file_exists($dir . '/' . $v . '/' . THEME_MANIFEST_INI)) {
                $themes_list[$type][$v] = parse_ini_file($dir . '/' . $v . '/' . THEME_MANIFEST_INI);
            }
            if (file_exists($dir . '/' . $v . '/customer_screenshot.png')) {
                $themes_list[$type][$v]['screenshot'] = Registry::get('config.current_location') . $rel_dir . '/' . $v . '/customer_screenshot.png';
            }
            // Check if the theme has styles.
            $params = array('short_info' => true);
            $themes_list[$type][$v]['styles'] = Styles::factory($v)->getList($params);
        }
    }
    $themes_list['current'] = $themes_list['installed'][$theme_name];
    $themes_list['current']['theme_name'] = $theme_name;
    return $themes_list;
}
Example #8
0
 private static function _installTheme($company_id = null)
 {
     $theme_name = 'basic';
     $style = 'satori';
     fn_install_theme($theme_name, $company_id);
     $layout = Layout::instance($company_id)->getDefault($theme_name);
     Styles::factory($theme_name)->setStyle($layout['layout_id'], $style);
 }
Example #9
0
 /**
  * Updates or creates layout
  * @param  array $layout_data layout data
  * @param  int   $layout_id   layout ID to update, zero to create
  * @return int   ID of updated/created layout
  */
 public function update($layout_data, $layout_id = 0)
 {
     $create = empty($layout_id);
     if (fn_allowed_for('ULTIMATE')) {
         if (empty($layout_data['company_id'])) {
             $layout_data['company_id'] = $this->_company_id;
         }
     }
     $theme_name = empty($layout_data['theme_name']) ? fn_get_theme_path('[theme]', 'C', $this->_company_id, false) : $layout_data['theme_name'];
     $available_styles = Styles::factory($theme_name)->getList(array('short_info' => true));
     /**
      * Performs actions before updating layout
      *
      * @param object  $this Layout object
      * @param integer $layout_id layout ID
      * @param array   $layout_data layout data
      * @param boolean $create create/update flag
      */
     fn_set_hook('layout_update_pre', $this, $layout_id, $layout_data, $create);
     // Create layout
     if (empty($layout_id)) {
         $company_id = !empty($layout_data['company_id']) ? $layout_data['company_id'] : 0;
         if (!empty($layout_data['from_layout_id'])) {
             $layout_data['style_id'] = Styles::factory($theme_name)->getStyle($layout_data['from_layout_id']);
         }
         if (!empty($layout_data['style_id']) && !isset($available_styles[$layout_data['style_id']])) {
             unset($layout_data['style_id']);
         }
         if (empty($layout_data['style_id'])) {
             $layout_data['style_id'] = Styles::factory($theme_name)->getDefault();
         }
         $layout_id = db_query("INSERT INTO ?:bm_layouts ?e", $layout_data);
     } else {
         if (isset($layout_data['style_id']) && !isset($available_styles[$layout_data['style_id']])) {
             $layout_data['style_id'] = Styles::factory($theme_name)->getDefault();
         }
         $old_layout_data = $this->get($layout_id);
         if ($old_layout_data['is_default'] == 1 && empty($layout_data['is_default'])) {
             $layout_data['is_default'] = 1;
         }
         db_query('UPDATE ?:bm_layouts SET ?u WHERE layout_id = ?i', $layout_data, $layout_id);
     }
     if (!empty($layout_data['is_default'])) {
         $this->setDefault($layout_id);
     }
     if (!empty($layout_data['from_layout_id'])) {
         $this->copyById($layout_data['from_layout_id'], $layout_id);
     }
     return $layout_id;
 }
Example #10
0
 /**
  * Fetch frontend styles
  *
  * @param array Params
  *
  * @return string Frontend styles
  */
 protected function fetchFrontendStyles($params = array())
 {
     fn_clear_cache('assets', 'design/');
     $style_id = Registry::get('runtime.layout.style_id');
     if (empty($style_id)) {
         Registry::set('runtime.layout.style_id', Styles::factory($this->theme_name)->getDefault());
     }
     $view = \Tygh::$app['view'];
     $view->setArea('C');
     $view->assign('use_scheme', true);
     $view->assign('include_dropdown', true);
     foreach ($params as $key => $val) {
         $view->assign($key, $val);
     }
     $ret = $view->fetch('common/styles.tpl');
     $view->setArea(AREA);
     return $ret;
 }
Example #11
0
/**
 * Init layout
 *
 * @param array $params request parameters
 * @return boolean always true
 */
function fn_init_layout($params)
{
    if (fn_allowed_for('ULTIMATE')) {
        if (!Registry::get('runtime.company_id')) {
            return array(INIT_STATUS_OK);
        }
    }
    $key_name = 'stored_layout' . (Embedded::isEnabled() ? '_embedded' : '');
    $stored_layout = fn_get_session_data($key_name);
    if (!empty($params['s_layout'])) {
        $stored_layout = $params['s_layout'];
        fn_set_session_data($key_name, $params['s_layout']);
    }
    // Replace default theme with selected for current area
    if (!empty($stored_layout)) {
        $layout = Layout::instance()->get($stored_layout);
        if (!isset($layout['theme_name']) || $layout['theme_name'] != fn_get_theme_path('[theme]', 'C')) {
            unset($layout);
        }
    }
    if (empty($layout)) {
        $layout = Layout::instance()->getDefault();
        // get default
    }
    $available_styles = Styles::factory($layout['theme_name'])->getList(array('short_info' => true));
    if (!isset($available_styles[$layout['style_id']])) {
        $layout['style_id'] = Styles::factory($layout['theme_name'])->getDefault();
    }
    Registry::set('runtime.layout', $layout);
    return array(INIT_STATUS_OK);
}
Example #12
0
    Registry::get('view')->assign('layout', $layout);
    foreach ($available_themes['installed'] as $theme_id => $theme) {
        $layouts_params = array('theme_name' => $theme_id);
        $available_themes['installed'][$theme_id]['layouts'] = Layout::instance()->getList($layouts_params);
        if ($theme_id == $theme_name) {
            $available_themes['current']['layouts'] = $available_themes['installed'][$theme_id]['layouts'];
        }
    }
    Registry::get('view')->assign('available_themes', $available_themes);
    Registry::get('view')->assign('dev_modes', Development::get());
} elseif ($mode == 'styles') {
    if ($action == 'update_status') {
        $theme = Themes::factory(fn_get_theme_path('[theme]', 'C'));
        $theme_manifest = $theme->getManifest();
        if (empty($theme_manifest['converted_to_css'])) {
            Styles::factory(fn_get_theme_path('[theme]', 'C'))->setStyle($_REQUEST['id'], $_REQUEST['status']);
            // Delete compiled CSS file
            fn_clear_cache('statics');
        } else {
            $layout = Layout::instance(Registry::get('runtime.company_id'))->getDefault();
            fn_set_notification('E', __('error'), __('theme_editor.error_theme_converted_to_css', array('[url]' => fn_url("customization.update_mode?type=theme_editor&status=enable&s_layout={$layout['layout_id']}"))));
        }
    }
    return array(CONTROLLER_STATUS_OK, 'themes.manage');
} elseif ($mode == 'update_dev_mode') {
    if (!empty($_REQUEST['dev_mode'])) {
        if (!empty($_REQUEST['state'])) {
            Development::enable($_REQUEST['dev_mode']);
        } else {
            Development::disable($_REQUEST['dev_mode']);
        }
Example #13
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);
    $theme_path = fn_get_theme_path('[theme]', 'C');
    $theme = Themes::factory($theme_path);
    $theme_manifest = $theme->getManifest();
    // Check file changes
    if (Development::isEnabled('compile_check') || Debugger::isActive()) {
        $dir_root = Registry::get('config.dir.root');
        $css_path = $dir_root . DIRECTORY_SEPARATOR . $relative_path;
        $tracked_files = array();
        $css_files = fn_get_dir_contents($css_path, false, true, array('css', 'less'), '', true);
        foreach ($css_files as $file) {
            $tracked_files[$file] = $css_path . DIRECTORY_SEPARATOR . $file;
        }
        foreach ($names as $index => $name) {
            if (file_exists($dir_root . '/' . $name)) {
                $tracked_files[$name] = $dir_root . '/' . $name;
            }
        }
        if ($area == 'C') {
            $style_id = Registry::get('runtime.layout.style_id');
            if ($style_id) {
                /** @var Styles $style */
                $style = Styles::factory(fn_get_theme_path('[theme]', $area));
                $less_file = $style->getStyleFile($style_id);
                $css_file = $style->getStyleFile($style_id, 'css');
                if (file_exists($less_file)) {
                    $tracked_files['less_' . $style_id] = $less_file;
                }
                if (file_exists($css_file)) {
                    $tracked_files['css_' . $style_id] = $css_file;
                }
            }
        }
        foreach ($tracked_files as $key => $file) {
            $hashes[] = $key . filemtime($file);
        }
    }
    $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';
    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;
}