/** * Prepares a string for use as a valid HTML ID and guarantees uniqueness. * * This function ensures that each passed HTML ID value only exists once on * the page. By tracking the already returned ids, this function enables * forms, blocks, and other content to be output multiple times on the same * page, without breaking (X)HTML validation. * * For already existing IDs, a counter is appended to the ID string. * Therefore, JavaScript and CSS code should not rely on any value that was * generated by this function and instead should rely on manually added CSS * classes or similarly reliable constructs. * * Two consecutive hyphens separate the counter from the original ID. To * manage uniqueness across multiple Ajax requests on the same page, Ajax * requests POST an array of all IDs currently present on the page, which are * used to prime this function's cache upon first invocation. * * To allow reverse-parsing of IDs submitted via Ajax, any multiple * consecutive hyphens in the originally passed $id are replaced with a * single hyphen. * * @param string $id * The ID to clean. * * @return string * The cleaned ID. */ public static function getUniqueId($id) { // If this is an Ajax request, then content returned by this page request // will be merged with content already on the base page. The HTML IDs must // be unique for the fully merged content. Therefore use unique IDs. if (static::$isAjax) { return static::getId($id) . '--' . Crypt::randomBytesBase64(8); } // @todo Remove all that code once we switch over to random IDs only, // see https://www.drupal.org/node/1090592. if (!isset(static::$seenIdsInit)) { static::$seenIdsInit = array(); } if (!isset(static::$seenIds)) { static::$seenIds = static::$seenIdsInit; } $id = static::getId($id); // Ensure IDs are unique by appending a counter after the first occurrence. // The counter needs to be appended with a delimiter that does not exist in // the base ID. Requiring a unique delimiter helps ensure that we really do // return unique IDs and also helps us re-create the $seen_ids array during // Ajax requests. if (isset(static::$seenIds[$id])) { $id = $id . '--' . ++static::$seenIds[$id]; } else { static::$seenIds[$id] = 1; } return $id; }