Loading features.module +1 −3 Original line number Diff line number Diff line Loading @@ -376,7 +376,6 @@ function features_include($reset = FALSE) { * collecting defaults. */ function features_include_defaults($components = NULL, $reset = FALSE) { static $included = array(); static $include_components; // Build an array of components that require inclusion: Loading @@ -399,7 +398,7 @@ function features_include_defaults($components = NULL, $reset = FALSE) { $components = array_keys($include_components); } foreach ($components as $component) { if (isset($include_components[$component]) && (!isset($included[$component]) || $reset)) { if (isset($include_components[$component])) { $info = $include_components[$component]; // Inclusion of ctools components. if (isset($info['api'], $info['module'], $info['current_version'])) { Loading @@ -416,7 +415,6 @@ function features_include_defaults($components = NULL, $reset = FALSE) { } } } $included[$component] = TRUE; } } } Loading includes/features.menu.inc +124 −22 Original line number Diff line number Diff line Loading @@ -142,7 +142,7 @@ function menu_links_features_export_options() { list($menu_name, $mlid) = explode(':', $key, 2); if ($mlid != 0) { $link = menu_link_load($mlid); $identifier = menu_links_features_identifier($link); $identifier = menu_links_features_identifier($link, TRUE); $options[$identifier] = "{$menu_name}: {$name}"; } } Loading @@ -153,8 +153,28 @@ function menu_links_features_export_options() { /** * Callback for generating the menu link exportable identifier. */ function menu_links_features_identifier($link) { return isset($link['menu_name'], $link['link_path']) ? "{$link['menu_name']}:{$link['link_path']}" : FALSE; function menu_links_features_identifier($link, $old = FALSE) { // Add some uniqueness to these identifiers, allowing multiple links with the same path, but different titles. $clean_title = features_clean_title(isset($link['title']) ? $link['title'] : $link['link_title']); // The old identifier is requested. if ($old) { // if identifier already exists if (isset($link['options']['identifier'])) { return $link['options']['identifier']; } // providing backward compatibility and allowing/enabling multiple links with same paths else { $identifier = isset($link['menu_name'], $link['link_path']) ? "{$link['menu_name']}:{$link['link_path']}" : FALSE; // Checking if there are multiples of this identifier if (features_menu_link_load($identifier) !== FALSE) { // this is where we return the upgrade posibility for links. return $identifier; } } } return isset($link['menu_name'], $link['link_path']) ? "{$link['menu_name']}_{$clean_title}:{$link['link_path']}" : FALSE; } /** Loading @@ -169,14 +189,15 @@ function menu_links_features_export($data, &$export, $module_name = '') { // Collect a link to module map $pipe = array(); $map = features_get_default_map('menu_links', 'menu_links_features_identifier'); foreach ($data as $identifier) { foreach ($data as $key => $identifier) { if ($link = features_menu_link_load($identifier)) { // If this link is provided by a different module, add it as a dependency. $new_identifier = menu_links_features_identifier($link, empty($export)); if (isset($map[$identifier]) && $map[$identifier] != $module_name) { $export['dependencies'][$map[$identifier]] = $map[$identifier]; } else { $export['features']['menu_links'][$identifier] = $identifier; $export['features']['menu_links'][$new_identifier] = $new_identifier; } // For now, exclude a variety of common menus from automatic export. // They may still be explicitly included in a Feature if the builder Loading @@ -192,23 +213,42 @@ function menu_links_features_export($data, &$export, $module_name = '') { /** * Implements hook_features_export_render() */ function menu_links_features_export_render($module, $data) { function menu_links_features_export_render($module, $data, $export = NULL) { $code = array(); $code[] = ' $menu_links = array();'; $code[] = ''; $translatables = array(); foreach ($data as $identifier) { if ($link = features_menu_link_load($identifier)) { $new_identifier = menu_links_features_identifier($link, empty($export)); // Replace plid with a parent path. if (!empty($link['plid']) && $parent = menu_link_load($link['plid'])) { // If the new identifier is different than the old, maintain // 'parent_path' for backwards compatibility. if ($new_identifier != menu_links_features_identifier($link)) { $link['parent_path'] = $parent['link_path']; } else { $clean_title = features_clean_title($parent['title']); $link['parent_identifier'] = "{$parent['menu_name']}_{$clean_title}:{$parent['link_path']}"; } } if (isset($export)) { // Don't show new identifier unless we are actually exporting. $link['options']['identifier'] = $new_identifier; // identifiers are renewed, => that means we need to update them in the db menu_link_save($temp = $link); } unset($link['plid']); unset($link['mlid']); $code[] = " // Exported menu link: {$identifier}"; $code[] = " \$menu_links['{$identifier}'] = ". features_var_export($link, ' ') .";"; $code[] = " // Exported menu link: {$new_identifier}"; $code[] = " \$menu_links['{$new_identifier}'] = ". features_var_export($link, ' ') .";"; $translatables[] = $link['link_title']; } } Loading Loading @@ -254,7 +294,7 @@ function menu_links_features_rebuild_ordered($menu_links, $reset = FALSE) { $current = count($unordered); foreach ($unordered as $key => $link) { $identifier = menu_links_features_identifier($link); $parent = isset($link['parent_path']) ? "{$link['menu_name']}:{$link['parent_path']}" : ''; $parent = isset($link['parent_identifier']) ? $link['parent_identifier'] : ''; if (empty($parent)) { $ordered[$identifier] = 0; $all_links[$identifier] = $link; Loading @@ -274,6 +314,7 @@ function menu_links_features_rebuild_ordered($menu_links, $reset = FALSE) { // Ensure any default menu items that do not exist are created. foreach (array_keys($ordered) as $identifier) { $link = $all_links[$identifier]; $existing = features_menu_link_load($identifier); if (!$existing || in_array($link, $menu_links)) { // Retrieve the mlid if this is an existing item. Loading @@ -281,7 +322,11 @@ function menu_links_features_rebuild_ordered($menu_links, $reset = FALSE) { $link['mlid'] = $existing['mlid']; } // Retrieve the plid for a parent link. if (!empty($link['parent_path']) && $parent = features_menu_link_load("{$link['menu_name']}:{$link['parent_path']}")) { if (!empty($link['parent_identifier']) && $parent = features_menu_link_load($link['parent_identifier'])) { $link['plid'] = $parent['mlid']; } // This if for backwards compatibility. elseif (!empty($link['parent_path']) && $parent = features_menu_link_load("{$link['menu_name']}:{$link['parent_path']}")) { $link['plid'] = $parent['mlid']; } else { Loading @@ -293,20 +338,77 @@ function menu_links_features_rebuild_ordered($menu_links, $reset = FALSE) { } /** * Load a menu link by its menu_name:link_path identifier. * Load a menu link by its menu_name_cleantitle:link_path identifier. * Also matches links with unique menu_name:link_path */ function features_menu_link_load($identifier) { $menu_name = ''; $link_path = ''; // This gets variables for menu_name_cleantitle:link_path format. if (strstr($identifier, "_")) { $link_path = substr($identifier, strpos($identifier, ":") + 1); list($menu_name) = explode('_', $identifier, 2); $clean_title = substr($identifier, strpos($identifier, "_") + 1, strpos($identifier, ":") - strpos($identifier, "_") - 1); } // This gets variables for traditional identifier format. else { $clean_title = ''; list($menu_name, $link_path) = explode(':', $identifier, 2); $link = db_select('menu_links') } $links = db_select('menu_links') ->fields('menu_links', array('menu_name', 'mlid', 'plid', 'link_path', 'router_path', 'link_title', 'options', 'module', 'hidden', 'external', 'has_children', 'expanded', 'weight')) ->condition('menu_name', $menu_name) ->condition('link_path', $link_path) ->addTag('features_menu_link') ->execute() ->fetchAssoc(); if ($link) { $link['options'] = unserialize($link['options']); return $link; ->fetchAllAssoc('mlid'); foreach($links as $link) { $link->options = unserialize($link->options); // Title or previous identifier matches. if ((isset($link->options['identifier']) && strcmp($link->options['identifier'], $identifier) == 0) || (isset($clean_title) && strcmp(features_clean_title($link->link_title), $clean_title) == 0)) { return (array)$link; } } // Only one link with the requested menu_name and link_path does exists, // -- providing an upgrade possibility for links saved in a feature before the // new identifier-pattern was added. if (count($links) == 1 && empty($clean_title)) { $link = reset($links); // get the first item return (array)$link; } // If link_path was changed on an existing link, we need to find it by // searching for link_title. else if (isset($clean_title)) { $links = db_select('menu_links') ->fields('menu_links', array('menu_name', 'mlid', 'plid', 'link_path', 'router_path', 'link_title', 'options', 'module', 'hidden', 'external', 'has_children', 'expanded', 'weight')) ->condition('menu_name', $menu_name) ->execute() ->fetchAllAssoc('mlid'); foreach($links as $link) { $link->options = unserialize($link->options); // title or previous identifier matches if ((isset($link->options['identifier']) && strcmp($link->options['identifier'], $identifier) == 0) || (isset($clean_title) && strcmp(features_clean_title($link->link_title), $clean_title) == 0)) { return (array)$link; } } } return FALSE; } /** * Returns a lowercase clean string with only letters, numbers and dashes */ function features_clean_title($str) { return strtolower(preg_replace_callback('/(\s)|([^a-zA-Z\-0-9])/i', create_function( '$matches', 'return $matches[1]?"-":"";' ), $str)); } Loading
features.module +1 −3 Original line number Diff line number Diff line Loading @@ -376,7 +376,6 @@ function features_include($reset = FALSE) { * collecting defaults. */ function features_include_defaults($components = NULL, $reset = FALSE) { static $included = array(); static $include_components; // Build an array of components that require inclusion: Loading @@ -399,7 +398,7 @@ function features_include_defaults($components = NULL, $reset = FALSE) { $components = array_keys($include_components); } foreach ($components as $component) { if (isset($include_components[$component]) && (!isset($included[$component]) || $reset)) { if (isset($include_components[$component])) { $info = $include_components[$component]; // Inclusion of ctools components. if (isset($info['api'], $info['module'], $info['current_version'])) { Loading @@ -416,7 +415,6 @@ function features_include_defaults($components = NULL, $reset = FALSE) { } } } $included[$component] = TRUE; } } } Loading
includes/features.menu.inc +124 −22 Original line number Diff line number Diff line Loading @@ -142,7 +142,7 @@ function menu_links_features_export_options() { list($menu_name, $mlid) = explode(':', $key, 2); if ($mlid != 0) { $link = menu_link_load($mlid); $identifier = menu_links_features_identifier($link); $identifier = menu_links_features_identifier($link, TRUE); $options[$identifier] = "{$menu_name}: {$name}"; } } Loading @@ -153,8 +153,28 @@ function menu_links_features_export_options() { /** * Callback for generating the menu link exportable identifier. */ function menu_links_features_identifier($link) { return isset($link['menu_name'], $link['link_path']) ? "{$link['menu_name']}:{$link['link_path']}" : FALSE; function menu_links_features_identifier($link, $old = FALSE) { // Add some uniqueness to these identifiers, allowing multiple links with the same path, but different titles. $clean_title = features_clean_title(isset($link['title']) ? $link['title'] : $link['link_title']); // The old identifier is requested. if ($old) { // if identifier already exists if (isset($link['options']['identifier'])) { return $link['options']['identifier']; } // providing backward compatibility and allowing/enabling multiple links with same paths else { $identifier = isset($link['menu_name'], $link['link_path']) ? "{$link['menu_name']}:{$link['link_path']}" : FALSE; // Checking if there are multiples of this identifier if (features_menu_link_load($identifier) !== FALSE) { // this is where we return the upgrade posibility for links. return $identifier; } } } return isset($link['menu_name'], $link['link_path']) ? "{$link['menu_name']}_{$clean_title}:{$link['link_path']}" : FALSE; } /** Loading @@ -169,14 +189,15 @@ function menu_links_features_export($data, &$export, $module_name = '') { // Collect a link to module map $pipe = array(); $map = features_get_default_map('menu_links', 'menu_links_features_identifier'); foreach ($data as $identifier) { foreach ($data as $key => $identifier) { if ($link = features_menu_link_load($identifier)) { // If this link is provided by a different module, add it as a dependency. $new_identifier = menu_links_features_identifier($link, empty($export)); if (isset($map[$identifier]) && $map[$identifier] != $module_name) { $export['dependencies'][$map[$identifier]] = $map[$identifier]; } else { $export['features']['menu_links'][$identifier] = $identifier; $export['features']['menu_links'][$new_identifier] = $new_identifier; } // For now, exclude a variety of common menus from automatic export. // They may still be explicitly included in a Feature if the builder Loading @@ -192,23 +213,42 @@ function menu_links_features_export($data, &$export, $module_name = '') { /** * Implements hook_features_export_render() */ function menu_links_features_export_render($module, $data) { function menu_links_features_export_render($module, $data, $export = NULL) { $code = array(); $code[] = ' $menu_links = array();'; $code[] = ''; $translatables = array(); foreach ($data as $identifier) { if ($link = features_menu_link_load($identifier)) { $new_identifier = menu_links_features_identifier($link, empty($export)); // Replace plid with a parent path. if (!empty($link['plid']) && $parent = menu_link_load($link['plid'])) { // If the new identifier is different than the old, maintain // 'parent_path' for backwards compatibility. if ($new_identifier != menu_links_features_identifier($link)) { $link['parent_path'] = $parent['link_path']; } else { $clean_title = features_clean_title($parent['title']); $link['parent_identifier'] = "{$parent['menu_name']}_{$clean_title}:{$parent['link_path']}"; } } if (isset($export)) { // Don't show new identifier unless we are actually exporting. $link['options']['identifier'] = $new_identifier; // identifiers are renewed, => that means we need to update them in the db menu_link_save($temp = $link); } unset($link['plid']); unset($link['mlid']); $code[] = " // Exported menu link: {$identifier}"; $code[] = " \$menu_links['{$identifier}'] = ". features_var_export($link, ' ') .";"; $code[] = " // Exported menu link: {$new_identifier}"; $code[] = " \$menu_links['{$new_identifier}'] = ". features_var_export($link, ' ') .";"; $translatables[] = $link['link_title']; } } Loading Loading @@ -254,7 +294,7 @@ function menu_links_features_rebuild_ordered($menu_links, $reset = FALSE) { $current = count($unordered); foreach ($unordered as $key => $link) { $identifier = menu_links_features_identifier($link); $parent = isset($link['parent_path']) ? "{$link['menu_name']}:{$link['parent_path']}" : ''; $parent = isset($link['parent_identifier']) ? $link['parent_identifier'] : ''; if (empty($parent)) { $ordered[$identifier] = 0; $all_links[$identifier] = $link; Loading @@ -274,6 +314,7 @@ function menu_links_features_rebuild_ordered($menu_links, $reset = FALSE) { // Ensure any default menu items that do not exist are created. foreach (array_keys($ordered) as $identifier) { $link = $all_links[$identifier]; $existing = features_menu_link_load($identifier); if (!$existing || in_array($link, $menu_links)) { // Retrieve the mlid if this is an existing item. Loading @@ -281,7 +322,11 @@ function menu_links_features_rebuild_ordered($menu_links, $reset = FALSE) { $link['mlid'] = $existing['mlid']; } // Retrieve the plid for a parent link. if (!empty($link['parent_path']) && $parent = features_menu_link_load("{$link['menu_name']}:{$link['parent_path']}")) { if (!empty($link['parent_identifier']) && $parent = features_menu_link_load($link['parent_identifier'])) { $link['plid'] = $parent['mlid']; } // This if for backwards compatibility. elseif (!empty($link['parent_path']) && $parent = features_menu_link_load("{$link['menu_name']}:{$link['parent_path']}")) { $link['plid'] = $parent['mlid']; } else { Loading @@ -293,20 +338,77 @@ function menu_links_features_rebuild_ordered($menu_links, $reset = FALSE) { } /** * Load a menu link by its menu_name:link_path identifier. * Load a menu link by its menu_name_cleantitle:link_path identifier. * Also matches links with unique menu_name:link_path */ function features_menu_link_load($identifier) { $menu_name = ''; $link_path = ''; // This gets variables for menu_name_cleantitle:link_path format. if (strstr($identifier, "_")) { $link_path = substr($identifier, strpos($identifier, ":") + 1); list($menu_name) = explode('_', $identifier, 2); $clean_title = substr($identifier, strpos($identifier, "_") + 1, strpos($identifier, ":") - strpos($identifier, "_") - 1); } // This gets variables for traditional identifier format. else { $clean_title = ''; list($menu_name, $link_path) = explode(':', $identifier, 2); $link = db_select('menu_links') } $links = db_select('menu_links') ->fields('menu_links', array('menu_name', 'mlid', 'plid', 'link_path', 'router_path', 'link_title', 'options', 'module', 'hidden', 'external', 'has_children', 'expanded', 'weight')) ->condition('menu_name', $menu_name) ->condition('link_path', $link_path) ->addTag('features_menu_link') ->execute() ->fetchAssoc(); if ($link) { $link['options'] = unserialize($link['options']); return $link; ->fetchAllAssoc('mlid'); foreach($links as $link) { $link->options = unserialize($link->options); // Title or previous identifier matches. if ((isset($link->options['identifier']) && strcmp($link->options['identifier'], $identifier) == 0) || (isset($clean_title) && strcmp(features_clean_title($link->link_title), $clean_title) == 0)) { return (array)$link; } } // Only one link with the requested menu_name and link_path does exists, // -- providing an upgrade possibility for links saved in a feature before the // new identifier-pattern was added. if (count($links) == 1 && empty($clean_title)) { $link = reset($links); // get the first item return (array)$link; } // If link_path was changed on an existing link, we need to find it by // searching for link_title. else if (isset($clean_title)) { $links = db_select('menu_links') ->fields('menu_links', array('menu_name', 'mlid', 'plid', 'link_path', 'router_path', 'link_title', 'options', 'module', 'hidden', 'external', 'has_children', 'expanded', 'weight')) ->condition('menu_name', $menu_name) ->execute() ->fetchAllAssoc('mlid'); foreach($links as $link) { $link->options = unserialize($link->options); // title or previous identifier matches if ((isset($link->options['identifier']) && strcmp($link->options['identifier'], $identifier) == 0) || (isset($clean_title) && strcmp(features_clean_title($link->link_title), $clean_title) == 0)) { return (array)$link; } } } return FALSE; } /** * Returns a lowercase clean string with only letters, numbers and dashes */ function features_clean_title($str) { return strtolower(preg_replace_callback('/(\s)|([^a-zA-Z\-0-9])/i', create_function( '$matches', 'return $matches[1]?"-":"";' ), $str)); }