/** * This method installs language values stored at so-named "Crowdin-pack directory". * The directory should have the following structure: * * / * /core.po - Core language values. Required. * /editions - Stores edition-specific *.po files. Optional. * /mve.po - Multivendor-specific file. * /addons - Stores add-ons' *.po files. Optional. * /banners.po * /bestsellers.po * /{addon name}.po * * This methods collects relevant *.po files from given directory and executes {@see Tygh\Languages\Languages::installLanguagePack()} method for each one. * "Relevant" means that only installed addons' po-files would be installed as well as mve.po will be installed only for Multivendor edition. * * @see Tygh\Languages\Languages::installLanguagePack() * * @param string $path Path to directory that contains .po files (i.e. PO-pack directory) * @param array $params Parameters passed to {@see Tygh\Languages\Languages::installLanguagePack()} function. * * @return bool|int (bool) false on failure, (bool) true on success or (int) ID of newly created language (if it was created successfully). */ public static function installCrowdinPack($path, $params) { $path = rtrim($path, '\\/') . '/'; $lang_meta = self::getLangPacksMeta($path, 'core.po', true); if (empty($lang_meta)) { $result = false; } else { fn_copy($path, Registry::get('config.dir.lang_packs') . $lang_meta['lang_code'] . '/'); $path = Registry::get('config.dir.lang_packs') . $lang_meta['lang_code'] . '/'; $result = self::installLanguagePack($path . 'core.po', $params); } if ($result) { $po_files_list = array(); if (fn_allowed_for('MULTIVENDOR') && file_exists($path . 'editions/mve.po')) { $po_files_list[] = $path . 'editions/mve.po'; } list($addons) = fn_get_addons(array('type' => 'installed')); foreach ($addons as $addon_id => $addon) { if (file_exists($path . 'addons/' . $addon_id . '.po')) { $po_files_list[] = $path . 'addons/' . $addon_id . '.po'; } } $params['reinstall'] = true; foreach ($po_files_list as $po_file) { $minor_result = self::installLanguagePack($po_file, $params); if (!$minor_result) { $result = false; break; } } } return $result; }
/** * 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; }
/** * Get theme CSS files list * * @return array CSS files list */ public function getCssFilesList() { $from = $this->theme_path . '/css'; $exclude = array('addons', self::$less_backup_dirname, self::$css_backup_dirname); $css_files = fn_get_dir_contents($from, false, true, '.css', '', true, $exclude); list($active_addons) = fn_get_addons(array('type' => 'active')); foreach ($active_addons as $addon_name => $addon) { $css_files = array_merge($css_files, fn_get_dir_contents($from . "/addons/{$addon_name}", false, true, '.css', "addons/{$addon_name}/", true)); } return $css_files; }
public static function installCrowdinPack($path, $params) { $path = fn_remove_trailing_slash($path) . '/'; if (file_exists($path . 'core.po') && is_dir($path . 'addons') && is_dir($path . 'editions')) { $lang_meta = self::getLangPacksMeta($path, 'core.po', true); if (empty($lang_meta['lang_code'])) { $result = false; fn_set_notification('E', __('error'), __('broken_po_pack')); } else { fn_copy($path, Registry::get('config.dir.lang_packs') . $lang_meta['lang_code'] . '/'); $path = Registry::get('config.dir.lang_packs') . $lang_meta['lang_code'] . '/'; $result = self::installLanguagePack($path . 'core.po', $params); } if ($result) { $po_files_list = array(); if (fn_allowed_for('MULTIVENDOR') && file_exists($path . 'editions/mve.po')) { $po_files_list[] = $path . 'editions/mve.po'; } list($addons) = fn_get_addons(array('type' => 'installed')); foreach ($addons as $addon_id => $addon) { if (file_exists($path . 'addons/' . $addon_id . '.po')) { $po_files_list[] = $path . 'addons/' . $addon_id . '.po'; } } foreach ($po_files_list as $po_file) { $result = self::installLanguagePack($po_file, array('reinstall' => true)); if (!$result) { break; } } } } else { fn_set_notification('E', __('error'), __('broken_po_pack')); return false; } return true; }
Registry::clearCachedKeyValues(); } if ($mode == 'uninstall') { fn_uninstall_addon($_REQUEST['addon']); } return array(CONTROLLER_STATUS_OK, 'addons.manage'); } if ($mode == 'update') { $addon_name = addslashes($_REQUEST['addon']); $section = Settings::instance()->getSectionByName($_REQUEST['addon'], Settings::ADDON_SECTION); if (empty($section)) { return array(CONTROLLER_STATUS_NO_PAGE); } $subsections = Settings::instance()->getSectionTabs($section['section_id'], CART_LANGUAGE); $options = Settings::instance()->getList($section['section_id']); fn_update_lang_objects('sections', $subsections); fn_update_lang_objects('options', $options); Tygh::$app['view']->assign('options', $options); Tygh::$app['view']->assign('subsections', $subsections); $addon = db_get_row('SELECT a.addon, a.status, b.name as name, b.description as description, a.separate ' . 'FROM ?:addons as a LEFT JOIN ?:addon_descriptions as b ON b.addon = a.addon AND b.lang_code = ?s WHERE a.addon = ?s' . 'ORDER BY b.name ASC', CART_LANGUAGE, $_REQUEST['addon']); if ($addon['separate'] == true || !defined('AJAX_REQUEST')) { Tygh::$app['view']->assign('separate', true); Tygh::$app['view']->assign('addon_name', $addon['name']); } } elseif ($mode == 'manage') { $params = $_REQUEST; $params['for_company'] = (bool) Registry::get('runtime.company_id'); list($addons, $search) = fn_get_addons($params); Tygh::$app['view']->assign('search', $search); Tygh::$app['view']->assign('addons_list', $addons); }