diff --git a/pathauto.install b/pathauto.install index dcca163..320835f 100644 --- a/pathauto.install +++ b/pathauto.install @@ -8,6 +8,39 @@ */ /** + * Implements hook_schema(). + */ +function pathauto_schema() { + $schema['pathauto'] = array( + 'description' => 'Holds the state of Pathauto\'s setting on any individual entity.', + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'description' => 'An entity type.', + ), + 'entity_id' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'description' => 'An entity ID.', + ), + 'pathauto' => array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'The automatic alias status of the entity.', + ), + ), + 'primary key' => array('entity_type', 'entity_id'), + ); + + return $schema; +} + +/** * Implements hook_install(). */ function pathauto_install() { @@ -169,6 +202,91 @@ function pathauto_update_7005() { } /** + * Create the pathauto table for storing path alias status. + */ +function pathauto_update_7006(&$sandbox) { + // Do not recreate if already existing from a D6 site. + if (db_table_exists('pathauto')) { + return; + } + + drupal_load('module', 'pathauto'); + module_load_include('inc', 'pathauto'); + + if (!isset($sandbox['progress'])) { + // Initialize the defaults for populating the table with Batch API. + $sandbox['progress'] = 0; + $sandbox['last_nid_processed'] = 0; + $sandbox['max'] = db_query("SELECT COUNT(*) FROM {node}")->fetchField(); + $sandbox['pathauto_persist'] = FALSE; + + // If the user used Pathauto persist, utilize the existing table. + if (db_table_exists('pathauto_persist')) { + db_rename_table('pathauto_persist', 'pathauto'); + module_disable(array('pathauto_persist')); + drupal_set_message(t('Pathauto persist has been disabled. This release of Pathauto includes its functionality and the old module may be removed.')); + $sandbox['pathauto_persist'] = TRUE; + } + // Create the new table. + else { + $table = array( + 'description' => 'Holds the state of Pathauto\'s setting on any individual entity.', + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'description' => 'An entity type.', + ), + 'entity_id' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'description' => 'An entity ID.', + ), + 'pathauto' => array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'The automatic alias status of the entity.', + ), + ), + 'primary key' => array('entity_type', 'entity_id'), + ); + db_create_table('pathauto', $table); + } + } + + // Populate the pathauto table 100 nodes at a time. + $result = db_query("SELECT nid, type, language FROM {node} WHERE nid > :nid LIMIT 100", array(':nid' => $sandbox['last_nid_processed']))->fetchAllAssoc('nid'); + foreach ($result as $row) { + // Check if this node already has an alias from Pathauto persist. + $existing_state = FALSE; + if ($sandbox['pathauto_persist']) { + $existing_state = db_query('SELECT entity_id FROM {pathauto} WHERE entity_id = :nid', array(':nid' => $row->nid))->fetchField(); + } + // And check if this node even would have an alias at all. + $pattern = pathauto_pattern_load_by_entity('node', $row->type, $row->language); + if ($pattern && !$existing_state) { + $node = node_load($row->nid); + $uri = entity_uri('node', $node); + $path = drupal_get_path_alias($uri['path'], $language); + $pathauto_alias = pathauto_create_alias('node', 'return', $uri['path'], array('node' => $node), $node->type, $node->language); + $node->path['pathauto'] = $path != $uri['path'] && $path == $pathauto_alias; + db_query("INSERT INTO {pathauto} (entity_type, entity_id, pathauto) VALUES (:entity_type, :entity_id, :pathauto)", array(':entity_type' => 'node', ':entity_id' => $node->nid, ':pathauto' => $node->path['pathauto'])); + } + + $sandbox['progress']++; + $sandbox['last_nid_processed'] = $node->nid; + } + + if ($sandbox['max']) { + $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max']; + } +} + +/** * Build a list of Drupal 6 tokens and their Drupal 7 token names. */ function _pathauto_upgrade_token_list() { diff --git a/pathauto.module b/pathauto.module index 947f9e1..f03d16c 100644 --- a/pathauto.module +++ b/pathauto.module @@ -168,6 +168,77 @@ function pathauto_pattern_load_by_entity($entity, $bundle = '', $language = LANG } /** + * Load a pathauto state for an entity. + * + * @param $entity_type + * An entity type. + * @param $entity_id + * An entity ID. + * @return + * The state of pathauto on this entity. Returns TRUE if automatic paths are + * enabled, FALSE if they are explicitly disabled, or NULL if the state is + * not known. + */ +function pathauto_entity_state_load($entity_type, $entity_id) { + $pathauto_state = pathauto_entity_state_load_multiple($entity_type, array($entity_id)); + return !empty($pathauto_state) ? reset($pathauto_state) : FALSE; +} + +/** + * Load a pathauto state for multiple entities. + * + * @param $entity_type + * An entity type. + * @param $entity_ids + * An array of entity IDs. + * @return + * An array of states, keyed by entity IDs. + */ +function pathauto_entity_state_load_multiple($entity_type, $entity_ids) { + $pathauto_state = db_query("SELECT entity_id, pathauto FROM {pathauto} WHERE entity_type = :entity_type AND entity_id IN (:entity_ids)", array(':entity_type' => $entity_type, ':entity_ids' => $entity_ids))->fetchAllKeyed(); + return $pathauto_state; +} + +/** + * Save the pathauto state for an entity. + * + * @param $entity_type + * An entity type. + * @param $entity + * The entity object. + * @param $pathauto_state + * A boolean flag if TRUE means that Pathauto should keep controlling this + * entity's path in the future. A FALSE value means Pathauto should stay out. + */ +function pathauto_entity_state_save($entity_type, $entity, $pathauto_state) { + list($entity_id) = entity_extract_ids($entity_type, $entity); + db_merge('pathauto') + ->key(array( + 'entity_type' => $entity_type, + 'entity_id' => $entity_id, + )) + ->fields(array( + 'pathauto' => $pathauto_state ? 1 : 0, + )) + ->execute(); +} + +/** + * Delete the pathauto state for an entity. + * + * @param $entity_type + * An entity type. + * @param $entity + * The entity object. + */ +function pathauto_entity_state_delete($entity_type, $entity_id) { + db_delete('pathauto') + ->condition('entity_type', $entity_type) + ->condition('entity_id', $entity_id) + ->execute(); +} + +/** * Delete multiple URL aliases. * * Intent of this is to abstract a potential path_delete_multiple() function @@ -455,6 +526,7 @@ function pathauto_node_update($node) { * Implements hook_node_delete(). */ function pathauto_node_delete($node) { + pathauto_entity_state_delete('node', $node->nid); pathauto_entity_path_delete_all('node', $node, "node/{$node->nid}"); } @@ -491,6 +563,15 @@ function pathauto_node_operations() { * An optional array of additional options. */ function pathauto_node_update_alias(stdClass $node, $op, array $options = array()) { + // Load the state (if any) from the database if not yet present. + if (!isset($node->path['pathauto'])) { + $node->path['pathauto'] = pathauto_entity_state_load('node', $node->nid); + } + // Save any updated state. + else { + pathauto_entity_state_save('node', $node, $node->path['pathauto']); + } + // Skip processing if the user has disabled pathauto for the node. if (isset($node->path['pathauto']) && empty($node->path['pathauto'])) { return;