diff --git a/pathauto.install b/pathauto.install index 7bd18db..3fb4080 100644 --- a/pathauto.install +++ b/pathauto.install @@ -8,9 +8,44 @@ */ /** + * 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() { + drupal_install_schema('pathauto'); + // Set some default variables necessary for the module to perform. variable_set('pathauto_node_pattern', 'content/[title-raw]'); variable_set('pathauto_taxonomy_pattern', '[vocab-raw]/[catpath-raw]'); @@ -29,6 +64,8 @@ function pathauto_install() { * Implements hook_uninstall(). */ function pathauto_uninstall() { + drupal_uninstall_schema('pathauto'); + // Delete all the pathauto variables and then clear the variable cache db_query("DELETE FROM {variable} WHERE name LIKE 'pathauto_%'"); cache_clear_all('variables', 'cache'); @@ -107,3 +144,90 @@ function pathauto_update_6201() { variable_del('pathauto_indexaliases_bulkupdate'); return array(); } + +/** + * Create the pathauto table for storing path alias status. + */ +function pathauto_update_6202(&$sandbox) { + $ret = array(); + + // Do not allow this to be run multiple times. + if (db_table_exists('pathauto')) { + return $ret; + } + + 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_result(db_query("SELECT COUNT(*) FROM {node}")); + $sandbox['pathauto_persist'] = FALSE; + + // If the user used Pathauto persist, utilize the existing table. + if (db_table_exists('pathauto_persist')) { + db_rename_table($ret, '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($ret, 'pathauto', $table); + } + } + + // Populate the pathauto table 100 nodes at a time. + $result = db_query("SELECT nid, type, language FROM {node} WHERE nid > %d LIMIT 100", $sandbox['last_nid_processed']); + while ($row = db_fetch_object($result)) { + // Check if this node already has an alias from Pathauto persist. + $existing_state = FALSE; + if ($sandbox['pathauto_persist']) { + $existing_state = db_result(db_query('SELECT entity_id FROM {pathauto} WHERE entity_id = %d', $row->nid)); + } + // 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); + $pathauto_alias = pathauto_create_alias('node', 'return', "node/{$node->nid}", array('node' => $node), $node->nid, $node->type, $node->language); + $node->pathauto_perform_alias = isset($node->path) && $node->path == $pathauto_alias; + db_query("INSERT INTO {pathauto} (entity_type, entity_id, pathauto) VALUES ('%s', %d, %d)", 'node', $node->nid, $node->pathauto_perform_alias); + } + + $sandbox['progress']++; + $sandbox['last_nid_processed'] = $node->nid; + } + + if ($sandbox['max']) { + $ret['#finished'] = $sandbox['progress'] / $sandbox['max']; + } + + return $ret; +} diff --git a/pathauto.module b/pathauto.module index 67c1c85..7f31d39 100644 --- a/pathauto.module +++ b/pathauto.module @@ -194,6 +194,53 @@ function pathauto_pattern_load_by_entity($entity, $bundle = '', $language = '', } /** + * 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 = db_result(db_query("SELECT pathauto FROM {pathauto} WHERE entity_type = '%s' AND entity_id = %d", $entity_type, $entity_id)); + return ($pathauto_state !== FALSE ? $pathauto_state : NULL); +} + +/** + * 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_id, $pathauto_state) { + db_query("UPDATE {pathauto} SET pathauto = %d WHERE entity_type = '%s' AND entity_id = %d", $pathauto_state, $entity_type, $entity_id); + if (!db_affected_rows()) { + db_query("INSERT INTO {pathauto} (entity_type, entity_id, pathauto) VALUES ('%s', %d, %d)", $entity_type, $entity_id, $pathauto_state); + } +} + +/** + * 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_query("DELETE FROM {pathauto} WHERE entity_type = '%s' AND entity_id = %d", $entity_type, $entity_id); +} + +/** * Delete an URL alias and any sub-paths. * * Given a source like 'node/1' this function will delete any alias that have @@ -284,6 +331,7 @@ function pathauto_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { break; case 'delete': pathauto_path_delete_all("node/{$node->nid}"); + pathauto_entity_state_delete('node', $node->nid); break; } } @@ -306,19 +354,21 @@ function pathauto_form_alter(&$form, $form_state, $form_id) { // If there is a pattern, show the automatic alias checkbox. if ($pattern) { - if (!isset($node->pathauto_perform_alias)) { - if (!empty($node->nid)) { - // If this is not a new node, compare it's current alias to the - // alias that would be genereted by pathauto. If they are the same, - // then keep the automatic alias enabled. + if (!empty($node->nid) && !isset($node->pathauto_perform_alias)) { + // Load the state of automatic aliasing (if any). + $node->pathauto_perform_alias = pathauto_entity_state_load('node', $node->nid); + + // If there isn't an explicit setting, make an educated guess as to + // whether it should be enabled by default. + if (is_null($node->pathauto_perform_alias)) { module_load_include('inc', 'pathauto'); $pathauto_alias = pathauto_create_alias('node', 'return', "node/{$node->nid}", array('node' => $node), $node->nid, $node->type, $node->language); $node->pathauto_perform_alias = isset($node->path) && $node->path == $pathauto_alias; } - else { - // If this is a new node, enable the automatic alias. - $node->pathauto_perform_alias = TRUE; - } + } + else { + // If this is a new node, enable the automatic alias. + $node->pathauto_perform_alias = TRUE; } // Add JavaScript that will disable the path textfield when the automatic @@ -379,6 +429,15 @@ function pathauto_node_operations() { * An optional array of additional options. */ function pathauto_node_update_alias($node, $op, $options = array()) { + // Load the state (if any) from the database if not yet present. + if (!isset($node->pathauto_perform_alias)) { + $node->pathauto_perform_alias = pathauto_entity_state_load('node', $node->nid); + } + // Save any updated state. + else { + pathauto_entity_state_save('node', $node->nid, $node->pathauto_perform_alias); + } + // Skip processing if the user has disabled pathauto for the node. if (isset($node->pathauto_perform_alias) && empty($node->pathauto_perform_alias)) { return;