$value) { Settings::instance()->updateValueById($setting_id, $value); if (!empty($_REQUEST['update_all_vendors'][$setting_id])) { Settings::instance()->resetAllVendorsSettings($setting_id); } } } return true; } /** * Uninstalles addon * * @param string $addon_name Addon name to be uninstalled * @param bool $show_message If defined as true, additionally show notification * @return bool True if addons uninstalled successfully, false otherwise */ function fn_uninstall_addon($addon_name, $show_message = true) { $addon_scheme = SchemesManager::getScheme($addon_name); if ($addon_scheme != false) { // Unmanaged addons can be uninstalled via console only if ($addon_scheme->getUnmanaged() && !defined('CONSOLE')) { return false; } // Check dependencies $dependencies = SchemesManager::getUninstallDependencies($addon_name); if (!empty($dependencies)) { fn_set_notification('W', __('warning'), __('text_addon_uninstall_dependencies', array( '[addons]' => implode(',', $dependencies) ))); return false; } // Execute custom functions for uninstall $addon_scheme->callCustomFunctions('uninstall'); $addon_description = db_get_field( "SELECT name FROM ?:addon_descriptions WHERE addon = ?s and lang_code = ?s", $addon_name, CART_LANGUAGE ); // Delete options db_query("DELETE FROM ?:addons WHERE addon = ?s", $addon_name); db_query("DELETE FROM ?:addon_descriptions WHERE addon = ?s", $addon_name); // Delete settings $section = Settings::instance()->getSectionByName($addon_name, Settings::ADDON_SECTION); if (isset($section['section_id'])) { Settings::instance()->removeSection($section['section_id']); } // Delete language variables $addon_scheme->uninstallLanguageValues(); // Revert database structure $addon_scheme->processQueries('uninstall', Registry::get('config.dir.addons') . $addon_name); // Remove product tabs ProductTabs::instance()->deleteAddonTabs($addon_name); fn_uninstall_addon_templates(fn_basename($addon_name)); if (file_exists(Registry::get('config.dir.addons') . $addon_name . '/layouts.xml')) { $xml = simplexml_load_file(Registry::get('config.dir.addons') . $addon_name . '/layouts.xml', '\\Tygh\\ExSimpleXmlElement', LIBXML_NOCDATA); foreach ($xml->location as $location) { if (fn_allowed_for('ULTIMATE')) { foreach (fn_get_all_companies_ids() as $company) { $layouts = Layout::instance($company)->getList(); foreach ($layouts as $layout_id => $layout) { Location::instance($layout_id)->removeByDispatch((string) $location['dispatch']); } } } else { $layouts = Layout::instance()->getList(); foreach ($layouts as $layout_id => $layout) { Location::instance($layout_id)->removeByDispatch((string) $location['dispatch']); } } } } if ($show_message) { fn_set_notification('N', __('notice'), __('text_addon_uninstalled', array( '[addon]' => $addon_scheme->getName() ))); } //Clean Registry Registry::del('addons.' . $addon_name); $hooks = Registry::get('hooks'); Registry::del('hooks'); if (!empty($hooks)) { foreach ($hooks as $hook_name => $hooks_data) { foreach ($hooks_data as $key => $hook_data) { if ($hook_data['addon'] === $addon_name) { unset($hooks[$hook_name][$key]); } } } } Registry::set('hooks', $hooks); // Clean cache fn_clear_cache(); return true; } else { return false; } } /** * Disables addon * * @param string $addon_name Addons name to be disabled * @param string $caller_addon_name TODO: NOT USED. Must be refactored. * @param bool $show_notification * @return bool Always true */ function fn_disable_addon($addon_name, $caller_addon_name, $show_notification = true) { $func = 'fn_settings_actions_addons_' . $addon_name; if (function_exists($func)) { $new_status = 'D'; $old_status = 'A'; $func($new_status, $old_status); } db_query("UPDATE ?:addons SET status = ?s WHERE addon = ?s", 'D', $addon_name); if ($show_notification == true) { fn_set_notification('N', __('notice'), __('status_changed')); } return true; } /** * Installes addon * * @param string $addon Addon to install * @param bool $show_notification Display notification if set to true * @param bool $install_demo If defined as true, addon's demo data will be installed * @return bool True if addons installed successfully, false otherwise */ function fn_install_addon($addon, $show_notification = true, $install_demo = false) { $status = db_get_field("SELECT status FROM ?:addons WHERE addon = ?s", $addon); // Return true if addon is installed if (!empty($status)) { return true; } $addon_scheme = SchemesManager::getScheme($addon); if (empty($addon_scheme)) { // Required add-on was not found in store. return false; } // Unmanaged addons can be installed via console only if ($addon_scheme->getUnmanaged() && !defined('CONSOLE')) { return false; } if ($addon_scheme != false) { // Register custom classes Registry::get('class_loader')->add('', Registry::get('config.dir.addons') . $addon); if ($addon_scheme->isPromo()) { $texts = fn_get_addon_permissions_text(); fn_set_notification('E', __('error'), $texts['text']); return false; } $_data = array ( 'addon' => $addon_scheme->getId(), 'priority' => $addon_scheme->getPriority(), 'dependencies' => implode(',', $addon_scheme->getDependencies()), 'conflicts' => implode(',', $addon_scheme->getConflicts()), 'requirements' => $addon_scheme->getRequirements(), 'version' => $addon_scheme->getVersion(), 'separate' => ($addon_scheme->getSettingsLayout() == 'separate') ? 1 : 0, 'has_icon' => $addon_scheme->hasIcon(), 'unmanaged' => $addon_scheme->getUnmanaged(), 'status' => 'D' // addon is disabled by default when installing ); // Check system requirements (needed versions, installed extensions, etc.) if (!$addon_scheme->checkRequirements($_data['requirements'])) { return false; } $dependencies = SchemesManager::getInstallDependencies($_data['addon']); if (!empty($dependencies)) { fn_set_notification('W', __('warning'), __('text_addon_install_dependencies', array( '[addon]' => implode(',', $dependencies) ))); return false; } if ($addon_scheme->callCustomFunctions('before_install') == false) { fn_uninstall_addon($addon, false); return false; } // Add add-on to registry Registry::set('addons.' . $addon, array( 'status' => 'D', 'priority' => $_data['priority'], )); // Execute optional queries if ($addon_scheme->processQueries('install', Registry::get('config.dir.addons') . $addon) == false) { fn_uninstall_addon($addon, false); return false; } if (fn_update_addon_settings($addon_scheme) == false) { fn_uninstall_addon($addon, false); return false; } db_query("REPLACE INTO ?:addons ?e", $_data); foreach ($addon_scheme->getAddonTranslations() as $translation) { db_query("REPLACE INTO ?:addon_descriptions ?e", array( 'lang_code' => $translation['lang_code'], 'addon' => $addon_scheme->getId(), 'name' => $translation['value'], 'description' => isset($translation['description']) ? $translation['description'] : '' )); } if ($original = $addon_scheme->getOriginals()) { db_query("REPLACE INTO ?:original_values ?e", array( 'msgctxt' => 'Addon:' . $addon, 'msgid' => $original['name'] )); db_query("REPLACE INTO ?:original_values ?e", array( 'msgctxt' => 'AddonDescription:' . $addon, 'msgid' => isset($original['description']) ? $original['description'] : '' )); } // Install templates fn_install_addon_templates($addon_scheme->getId()); // Put this addon settings to the registry $settings = Settings::instance()->getValues($addon_scheme->getId(), Settings::ADDON_SECTION, false); if (!empty($settings)) { Registry::set('settings.' . $addon, $settings); $addon_data = Registry::get('addons.' . $addon); Registry::set('addons.' . $addon, fn_array_merge($addon_data, $settings)); } // Add optional language variables $language_variables = $addon_scheme->getLanguageValues(false); if (!empty($language_variables)) { db_query('REPLACE INTO ?:language_values ?m', $language_variables); } // Get only original values $language_variables = $addon_scheme->getLanguageValues(true); if (!empty($language_variables)) { db_query('REPLACE INTO ?:original_values ?m', $language_variables); } if (fn_allowed_for('ULTIMATE')) { foreach (fn_get_all_companies_ids() as $company) { ProductTabs::instance($company)->createAddonTabs($addon_scheme->getId(), $addon_scheme->getTabOrder()); } } else { ProductTabs::instance()->createAddonTabs($addon_scheme->getId(), $addon_scheme->getTabOrder()); } // Execute custom functions if ($addon_scheme->callCustomFunctions('install') == false) { fn_uninstall_addon($addon, false); return false; } if ($show_notification == true) { fn_set_notification('N', __('notice'), __('text_addon_installed', array( '[addon]' => $addon_scheme->getName() ))); } // If we need to activate addon after install, call "update status" procedure if ($addon_scheme->getStatus() != 'D') { fn_update_addon_status($addon, $addon_scheme->getStatus(), false); } if (file_exists(Registry::get('config.dir.addons') . $addon . '/layouts.xml')) { if (fn_allowed_for('ULTIMATE')) { foreach (fn_get_all_companies_ids() as $company) { $layouts = Layout::instance($company)->getList(); foreach ($layouts as $layout_id => $layout) { Exim::instance($company, $layout_id)->importFromFile(Registry::get('config.dir.addons') . $addon . '/layouts.xml'); } } } else { $layouts = Layout::instance()->getList(); foreach ($layouts as $layout_id => $layout) { Exim::instance(0, $layout_id)->importFromFile(Registry::get('config.dir.addons') . $addon . '/layouts.xml'); } } } // Clean cache fn_clear_cache(); if ($install_demo) { $addon_scheme->processQueries('demo', Registry::get('config.dir.addons') . $addon); if ($addon_scheme->callCustomFunctions('demo') == false) { fn_uninstall_addon($addon, false); return false; } } return true; } else { // Addon was not installed because scheme is not exists. return false; } } /** * Copies addon templates from repository * * @param string $addon_name Addons name to copy templates for * @return bool Always true */ function fn_install_addon_templates($addon_name) { $installed_themes = fn_get_installed_themes(); $design_dir = fn_get_theme_path('[themes]/', 'C'); foreach ($installed_themes as $theme_name) { $manifest = Themes::factory($theme_name)->getRepoManifest(); if (empty($manifest)) { $manifest = Themes::factory($theme_name)->getManifest(); } if (isset($manifest['parent_theme'])) { if (empty($manifest['parent_theme'])) { $parent_path = fn_get_theme_path('[repo]/' . $theme_name . '/'); } else { $parent_path = fn_get_theme_path('[repo]/' . $manifest['parent_theme'] . '/'); } } else { $parent_path = fn_get_theme_path('[repo]/' . Registry::get('config.base_theme') . '/'); } $repo_path = array( fn_get_theme_path('[repo]/basic' . '/'), $parent_path, fn_get_theme_path('[repo]/' . $theme_name . '/') ); foreach ($repo_path as $path) { fn_copy_addon_templates_from_repo($path, $design_dir, $addon_name, $theme_name); } } return true; } /** * Copies files from base repository to store folder * * @param string $repo_dir Path to the repository * @param string $design_dir Path to store design folder * @param string $addon_name Name of installing add-on * @param string $theme_name Using theme name */ function fn_copy_addon_templates_from_repo($repo_dir, $design_dir, $addon_name, $theme_name) { $paths = array( 'templates/addons/' . $addon_name, 'css/addons/' . $addon_name, 'media/images/addons/' . $addon_name, // Copy Mail directory 'mail/templates/addons/' . $addon_name, 'mail/media/images/addons/' . $addon_name, 'mail/css/addons/' . $addon_name, ); foreach ($paths as $path) { if (is_dir($repo_dir . $path)) { fn_copy($repo_dir . $path, $design_dir . $theme_name . '/' . $path); } } } /** * Removes addon's templates from theme folder * * @param string $addon Addon name to remove templates for * @return bool Always true */ function fn_uninstall_addon_templates($addon) { if (defined('DEVELOPMENT')) { return false; } $installed_themes = fn_get_installed_themes(); $design_dir = fn_get_theme_path('[themes]/', 'C'); foreach ($installed_themes as $theme_name) { $paths = array( $design_dir . $theme_name . '/templates/addons/' . $addon, $design_dir . $theme_name . '/css/addons/' . $addon, $design_dir . $theme_name . '/media/images/addons/' . $addon, $design_dir . $theme_name . '/mail/templates/addons/' . $addon, $design_dir . $theme_name . '/mail/media/images/addons/' . $addon, $design_dir . $theme_name . '/mail/css/addons/' . $addon, ); foreach ($paths as $path) { if (is_dir($path)) { fn_rm($path); } } } return true; } /** * Updates addon settings in database * * @param XmlScheme $addon_scheme Data from addon.xml file * @return bool True in success, false otherwise */ function fn_update_addon_settings($addon_scheme, $execute_functions = true) { $tabs = $addon_scheme->getSections(); // If isset section settings in xml data and that addon settings is not exists if (!empty($tabs)) { Registry::set('runtime.database.skip_errors', true); // Create root settings section $addon_section_id = Settings::instance()->updateSection(array( 'parent_id' => 0, 'edition_type' => $addon_scheme->getEditionType(), 'name' => $addon_scheme->getId(), 'type' => Settings::ADDON_SECTION, )); foreach ($tabs as $tab_index => $tab) { // Add addon tab as setting section tab $section_tab_id = Settings::instance()->updateSection(array( 'parent_id' => $addon_section_id, 'edition_type' => $tab['edition_type'], 'name' => $tab['id'], 'position' => $tab_index * 10, 'type' => isset($tab['separate']) ? Settings::SEPARATE_TAB_SECTION : Settings::TAB_SECTION, )); // Import translations for tab if (!empty($section_tab_id)) { fn_update_addon_settings_descriptions($section_tab_id, Settings::SECTION_DESCRIPTION, $tab['translations']); $settings = $addon_scheme->getSettings($tab['id']); foreach ($settings as $k => $setting) { if (!empty($setting['id'])) { if (!empty($setting['parent_id'])) { $setting['parent_id'] = Settings::instance()->getId($setting['parent_id'], $addon_scheme->getId()); } $setting_id = Settings::instance()->update(array( 'name' => $setting['id'], 'section_id' => $addon_section_id, 'section_tab_id' => $section_tab_id, 'type' => $setting['type'], 'position' => isset($setting['position']) ? $setting['position'] : $k * 10, 'edition_type' => $setting['edition_type'], 'is_global' => 'N', 'handler' => $setting['handler'], 'parent_id' => intval($setting['parent_id']) )); if (!empty($setting_id)) { Settings::instance()->updateValueById($setting_id, $setting['default_value'], null, $execute_functions); fn_update_addon_settings_descriptions($setting_id, Settings::SETTING_DESCRIPTION, $setting['translations']); if (isset($setting['variants'])) { foreach ($setting['variants'] as $variant_k => $variant) { $variant_id = Settings::instance()->updateVariant(array( 'object_id' => $setting_id, 'name' => $variant['id'], 'position' => isset($variant['position']) ? $variant['position'] : $variant_k * 10, )); if (!empty($variant_id)) { fn_update_addon_settings_descriptions($variant_id, Settings::VARIANT_DESCRIPTION, $variant['translations']); } } } } } } } } Registry::set('runtime.database.skip_errors', false); $errors = Registry::get('runtime.database.errors'); if (!empty($errors)) { $error_text = ''; foreach ($errors as $error) { $error_text .= '
' . $error['message'] . ': '. $error['query'] . ''; } fn_set_notification('E', __('addon_sql_error'), $error_text); return false; } } return true; } /** * Updates addon settings descriptions * * @param int $object_id Descriptions identifier * @param string $object_type Descriptions type (Settings::VARIANT_DESCRIPTION | Settings::SETTING_DESCRIPTION | Settings::SECTION_DESCRIPTION) * @param array $translations List of descriptions @see Settings::updateDescription() * @return bool Always true */ function fn_update_addon_settings_descriptions($object_id, $object_type, $translations) { if (!empty($translations)) { foreach ($translations as $translation) { $translation['object_type'] = $object_type; $translation['object_id'] = $object_id; Settings::instance()->updateDescription($translation); } } return true; } /** * Checks if addon has correct shaphot * * @param string $addon Addon name (ID) * @return bool true if correct */ function fn_check_addon_snapshot($addon) { static $addons_snapshots = array(); static $mode = ''; $status = true; if (empty($addons_snapshots)) { $addons_snapshots = fn_get_storage_data('addons_snapshots'); $addons_snapshots = explode(',', $addons_snapshots); $mode = fn_get_storage_data('store_mode'); } if ($mode == strrev('eerf') && in_array(md5($addon), $addons_snapshots)) { $status = false; } fn_set_hook('addon_snapshot', $addon, $status); return $status; } /** * Cleans up addons with incorrect snaphost * * @return bool Always true */ function fn_clean_up_addons() { $_addons = db_get_hash_single_array("SELECT addon, status FROM ?:addons", array('addon', 'status')); $skipped_snapshots = fn_get_storage_data('skipped_snapshots'); $skipped_snapshots = !empty($skipped_snapshots) ? explode(',', $skipped_snapshots) : array(); foreach ($_addons as $addon => $status) { $snaphost = md5(str_rot13($addon)); if (!fn_check_addon_snapshot($addon)) { if ($status == 'A') { fn_update_addon_status($addon, 'D'); $skipped_snapshots[] = $snaphost; } } elseif (in_array($snaphost, $skipped_snapshots)) { fn_update_addon_status($addon, 'A'); $skipped_snapshots = array_diff($skipped_snapshots, array($snaphost)); } } $skipped_snapshots = array_unique($skipped_snapshots); fn_set_storage_data('skipped_snapshots', implode(',', $skipped_snapshots)); return true; } /** * Updates addon status * @param string $addon Addon to update status for * @param string $status Status to change to * @param bool $show_notification Display notification if set to true * @param bool $on_install If status was changed right after install process * @return bool|string True on success, old status ID if status was not changed */ function fn_update_addon_status($addon, $status, $show_notification = true, $on_install = false) { $old_status = db_get_field("SELECT status FROM ?:addons WHERE addon = ?s", $addon); $new_status = $status; $scheme = SchemesManager::getScheme($addon); // Unmanaged addons can be enabled/disabled via console only if ($scheme->getUnmanaged() && !defined('CONSOLE')) { return false; } if ($old_status != $new_status) { // Check if addon can be enabled $conflicts = db_get_fields("SELECT addon FROM ?:addons WHERE status = 'A' AND FIND_IN_SET(?s, conflicts)", $addon); if ($new_status == 'A' && !empty($conflicts)) { $scheme = SchemesManager::getScheme($addon); fn_set_notification('W', __('warning'), __('text_addon_cannot_enable', array( '[addons]' => implode(', ', SchemesManager::getNames($conflicts)), '[addon_name]' => $scheme->getName() ))); return $old_status; } fn_get_schema('settings', 'actions.functions', 'php', true); $func = 'fn_settings_actions_addons_' . $addon; if (function_exists($func)) { $func($new_status, $old_status, $on_install); } // If status change is allowed, update it if ($old_status != $new_status) { if ($new_status != 'D') { // Check that addon have conflicts $scheme = SchemesManager::getScheme($addon); $conflicts = db_get_field("SELECT conflicts FROM ?:addons WHERE addon = ?s", $addon); if (!empty($conflicts)) { $conflicts = explode(',', $conflicts); $conflicted_addons = db_get_fields("SELECT addon FROM ?:addons WHERE addon IN (?a) AND status = 'A'", $conflicts); if (!empty($conflicted_addons)) { $lang_var = 'text_addon_confclicts_on_install'; if (!$on_install) { foreach ($conflicts as $conflict) { fn_disable_addon($conflict, $scheme->getName(), $show_notification); } $lang_var = 'text_addon_confclicts'; } fn_set_notification('W', __('warning'), __($lang_var, array( '[addons]' => implode(', ', SchemesManager::getNames($conflicts)), '[addon_name]' => $scheme->getName() ))); // On install we cannot enable addon with conflicts automaticly if ($on_install) { return $old_status; } } } } db_query("UPDATE ?:addons SET status = ?s WHERE addon = ?s", $status, $addon); $func = 'fn_settings_actions_addons_post_' . $addon; if (function_exists($func)) { $func($status); } if ($show_notification == true) { fn_set_notification('N', __('notice'), __('status_changed')); } // Enable/disable tabs for addon ProductTabs::instance()->updateAddonTabStatus($addon, $new_status); Registry::set('addons.' . $addon . '.status', $status); } else { return $old_status; } } // Clean cache fn_clear_cache(); if ($status == 'A') { foreach (fn_get_installed_themes() as $theme_name) { $theme = Themes::factory($theme_name); $theme_manifest = $theme->getManifest(); // Precompile addon LESS files if the theme has been converted to CSS if (!empty($theme_manifest['converted_to_css']) && !$theme->convertAddonToCss($addon)) { fn_update_addon_status($addon, 'D', $show_notification, $on_install); return $old_status; } } } return true; } /** * Returns addon's version * @param string $addon Addon name to return version for * @return string Addon's version */ function fn_get_addon_version($addon) { return db_get_field("SELECT version FROM ?:addons where addon=?s", $addon); } /** * Gets addons list * * @param array $params search params * @param int $items_per_page items per page for pagination * @param string $lang_code language code * @return array addons list and filtered search params */ function fn_get_addons($params, $items_per_page = 0, $lang_code = CART_LANGUAGE) { $params = LastView::instance()->update('addons', $params); $default_params = array( 'type' => 'any', ); $params = array_merge($default_params, $params); $addons = array(); $sections = Settings::instance()->getAddons(); $all_addons = fn_get_dir_contents(Registry::get('config.dir.addons'), true, false); $installed_addons = db_get_hash_array( 'SELECT a.addon, a.status, b.name as name, b.description as description, a.separate, a.unmanaged, a.has_icon ' . 'FROM ?:addons as a LEFT JOIN ?:addon_descriptions as b ON b.addon = a.addon AND b.lang_code = ?s' . 'ORDER BY b.name ASC', 'addon', $lang_code ); foreach ($installed_addons as $key => $addon) { $installed_addons[$key]['has_sections'] = Settings::instance()->sectionExists($sections, $addon['addon']); $installed_addons[$key]['has_options'] = ($installed_addons[$key]['has_sections']) ? Settings::instance()->optionsExists($addon['addon'], 'ADDON') : false; // Check add-on snaphot if (!fn_check_addon_snapshot($key)) { $installed_addons[$key]['status'] = 'D'; $installed_addons[$key]['snapshot_correct'] = false; } else { $installed_addons[$key]['snapshot_correct'] = true; } } foreach ($all_addons as $addon) { $addon_scheme = SchemesManager::getScheme($addon); if (in_array($params['type'], array('any', 'installed', 'active', 'disabled'))) { $search_status = $params['type'] == 'active' ? 'A' : ($params['type'] == 'disabled' ? 'D' : ''); if (!empty($installed_addons[$addon])) { // exclude unmanaged addons from the list if ($installed_addons[$addon]['unmanaged'] == true) { continue; } if (!empty($search_status) && $installed_addons[$addon]['status'] != $search_status) { continue; } $addons[$addon] = $installed_addons[$addon]; $addons[$addon]['delete_url'] = ''; $addons[$addon]['url'] = fn_url("addons.update?addon=$addon&return_url=" . urlencode(Registry::get('config.current_url'))); if (!Registry::get('runtime.company_id')) { $addons[$addon]['delete_url'] = fn_url("addons.uninstall?addon=$addon&redirect_url=" . urlencode(Registry::get('config.current_url'))); } if ($addon_scheme != false && !$addon_scheme->getUnmanaged()) { $addons[$addon]['originals'] = $addon_scheme->getOriginals(); } fn_update_lang_objects('installed_addon', $addons[$addon]); if (is_file(Registry::get('config.dir.addons') . $addon . '/func.php')) { require_once(Registry::get('config.dir.addons') . $addon . '/func.php'); if (is_file(Registry::get('config.dir.addons') . $addon . '/config.php')) { require_once(Registry::get('config.dir.addons') . $addon . '/config.php'); } // Generate custom description $func = 'fn_addon_dynamic_description_' . $addon; if (function_exists($func)) { $addons[$addon]['description'] = $func($addons[$addon]['description']); } //Generate custom url $url_func = 'fn_addon_dynamic_url_' . $addon; if (function_exists($url_func)) { list($addons[$addon]['url'], $addons[$addon]['delete_url']) = $url_func($addons[$addon]['url'], $addons[$addon]['delete_url']); } } } } if (empty($installed_addons[$addon]) && empty($params['for_company']) && (in_array($params['type'], array('any', 'not_installed')))) { if ($addon_scheme != false && !$addon_scheme->getUnmanaged()) { $addons[$addon] = array( 'status' => 'N', // Because it's not installed 'name' => $addon_scheme->getName(), 'snapshot_correct' => fn_check_addon_snapshot($addon), 'description' => $addon_scheme->getDescription(), 'has_icon' => $addon_scheme->hasIcon(), ); } } } if (!empty($params['q'])) { foreach ($addons as $addon => $addon_data) { if (!preg_match('/' . preg_quote($params['q'], '/') . '/ui', $addon_data['name'], $m)) { unset($addons[$addon]); } } } $addons = fn_sort_array_by_key($addons, 'name', SORT_ASC); return array($addons, $params); } /** * Move addon pack from temporarily folder to specified place and install it if possible * * @param string $from Source path * @param string $to Destination path * @return bool true if installed, false otherwise */ function fn_addons_move_and_install($from, $to) { if (defined('AJAX_REQUEST')) { Registry::get('ajax')->assign('non_ajax_notifications', true); } $struct = fn_get_dir_contents($from, false, true, '', '', true); $addon_name = ''; foreach ($struct as $file) { if (preg_match('/app.+?addons[^a-zA-Z0-9_]+([a-zA-Z0-9_-]+).+?addon.xml$/i', $file, $matches)) { if (!empty($matches[1])) { $addon_name = $matches[1]; break; } } } $relative_addon_path = str_replace(Registry::get('config.dir.root') . '/', '', Registry::get('config.dir.addons')); if (!file_exists($from . $relative_addon_path . $addon_name . '/addon.xml')) { fn_set_notification('E', __('error'), __('broken_addon_pack')); return false; } fn_copy($from, $to); fn_install_addon($addon_name); fn_rm($from); return true; } function fn_get_addon_permissions_text() { $messages = array( 'title' => __('text_full_mode_required'), 'text' => __('text_forbidden_functionality') ); fn_set_hook('addon_permissions_text', $messages); return $messages; } /** * Load addon * * @param string $addon_name addon name * @return boolean true if addon loaded, false otherwise */ function fn_load_addon($addon_name) { static $cache = array(); // FIXME: duplicate with fn_set_hook if (!isset($cache[$addon_name])) { if (is_file(Registry::get('config.dir.addons') . $addon_name . '/init.php')) { include_once(Registry::get('config.dir.addons') . $addon_name . '/init.php'); } if (file_exists(Registry::get('config.dir.addons') . $addon_name . '/func.php')) { include_once(Registry::get('config.dir.addons') . $addon_name . '/func.php'); } if (file_exists(Registry::get('config.dir.addons') . $addon_name . '/config.php')) { include_once(Registry::get('config.dir.addons') . $addon_name . '/config.php'); } Registry::get('class_loader')->add('', Registry::get('config.dir.addons') . $addon_name); $cache[$addon_name] = true; } return $cache[$addon_name]; }