diff --git a/amp.install b/amp.install index 2a0acda..bae876c 100644 --- a/amp.install +++ b/amp.install @@ -48,3 +48,48 @@ function amp_requirements($phase) { } return $requirements; } + +/** + * Implements hook_install. + * + * Add new table for unpublished AMP nodes. + */ +function amp_schema() { + $schema['amp_node'] = array( + 'description' => 'Stores preferences for amp nodes.', + 'primary key' => array('aid'), + 'fields' => array( + 'aid' => array( + 'description' => 'The {amp}.id of the amp node.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'status' => array( + 'description' => 'Boolean indicating whether the node is AMP enabled by default.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 1, + 'size' => 'tiny', + ), + ), + 'indexes' => array( + 'aid' => array('aid'), + 'status' => array('status'), + ), + ); + + return $schema; +} + +/** + * Add new table to track unpublished AMP nodes. + */ +function amp_update_7001() { + if (!db_table_exists('amp_node')) { + drupal_install_schema('amp'); + } + +} diff --git a/amp.module b/amp.module index 3792dba..aba7f1b 100644 --- a/amp.module +++ b/amp.module @@ -361,9 +361,15 @@ function amp_is_amp_request() { * Implements hook_custom_theme(). */ function amp_custom_theme() { - if (amp_is_amp_request()) { - return variable_get('amp_theme', 'ampsubtheme_example'); - } + $node = menu_get_object(); + + if (amp_is_amp_request()) { + // Performance note: Just load this file when we know is an AMP request. + module_load_include('inc', 'amp', 'inc/amp.db'); + if (amp_node_is_enabled($node->nid)) { + return variable_get('amp_theme', 'ampsubtheme_example'); + } + } } /** @@ -400,6 +406,38 @@ function amp_form_node_form_alter(&$form, &$form_state, $form_id) { '#weight' => 13, '#access' => TRUE, ); + + module_load_include('inc', 'amp', 'inc/amp.db'); + // Disable amp checkbox. + $form['options']['amp_enabled'] = array( + '#title' => t('Published (AMP)'), + '#type' => 'checkbox', + // if AMP_disabled == TRUE, means AMP is enabled, or AMP_enabled == FALSE; + '#default_value' => amp_node_is_enabled($form_state['node']->nid), + ); + + $form['actions']['submit']['#submit'][] = 'amp_form_submit'; + } +} + +/** + * Implements amp_form_submit. + */ +function amp_form_submit($form, &$form_state) { + module_load_include('inc', 'amp', 'inc/amp.db'); + if ($form_state['values']['amp_enabled'] == 0) { + amp_db_disable_amp($form_state['nid']); + amp_clear_cache($form_state['nid']); + } + elseif ($form_state['values']['amp_enabled'] == 1 && !amp_node_is_enabled($form_state['nid'])) { + // If the form says enable, and it was disabled, enable it back. + try { + amp_db_enable_amp($form_state['nid']); + amp_clear_cache($form_state['nid']); + } + catch (Exception $ex) { + watchdog('amp', "DB Exception: We couldn't disable the AMP version of the node"); + } } } @@ -647,10 +685,13 @@ function amp_page_alter(array &$page) { function amp_node_view($node, $view_mode, $langcode) { // Show amphtml links on AMP-enabled nodes so search engines can find AMP. if ($view_mode == 'full' && node_is_page($node) && in_array($node->type, amp_get_enabled_types())) { - $uri = entity_uri('node', $node); - $uri['options']['query']['amp'] = NULL; - $uri['options']['absolute'] = TRUE; - drupal_add_html_head_link(array('rel' => 'amphtml', 'href' => url($uri['path'], $uri['options'])), TRUE); + module_load_include('inc', 'amp', 'inc/amp.db'); + if (amp_node_is_enabled($build['#node']->nid)) { + $uri = entity_uri('node', $node); + $uri['options']['query']['amp'] = NULL; + $uri['options']['absolute'] = TRUE; + drupal_add_html_head_link(array('rel' => 'amphtml', 'href' => url($uri['path'], $uri['options'])), TRUE); + } } // Add AMP metadata. @@ -1444,11 +1485,65 @@ function amp_deliver_html_page($page_callback_result) { */ function amp_page_delivery_callback_alter(&$deliver_callback) { if (amp_is_amp_request()) { - $deliver_callback = 'amp_deliver_html_page'; + $node = menu_get_object(); + module_load_include('inc', 'amp', 'inc/amp.db'); + if (amp_node_is_enabled($node->nid)) { + $deliver_callback = 'amp_deliver_html_page'; + } } } /** + * Implements hook_node_delete(). + */ +function amp_node_delete($node) { + if (in_array($node->type, amp_get_enabled_types())) { + // We don't need the amp table for this node if it gets removed. + module_load_include('inc', 'amp', 'inc/amp.db'); + amp_db_remove($node->nid); + amp_clear_cache($node->id); + } +} + +/** + * Clear cache with id $id + * + * @param $id + * ID of the cache to clear. + */ +function amp_clear_cache($id) { + // Clear bins as we have fresh data. + cache_clear_all('amp:node_enabled:' . $id, 'cache_amp'); +} + +/** + * Get if the node is enabled. + * + * @param $nodeid + * Node id to check. + * + * @return bool + * TRUE if enabled, FALSE otherwise. + */ +function amp_node_is_enabled($nodeid, $cache_override = FALSE) { + // Setup a cache ID + $cid = 'amp:node_enabled:' . $nodeid; + + // If a cached entry exists, return it + if ($cached = cache_get($cid) && $cache_override != TRUE) { + $is_enabled = $cached->data; + } + else { + $is_enabled = amp_db_is_node_enabled($nodeid); + + // Cache the result. + cache_set($cid, $is_enabled, 'cache_amp'); + } + + return $is_enabled; +} + +/** * Implements hook_html_head_alter(). */ function amp_html_head_alter(&$head_elements) { diff --git a/inc/amp.db.inc b/inc/amp.db.inc new file mode 100644 index 0000000..d1e9806 --- /dev/null +++ b/inc/amp.db.inc @@ -0,0 +1,104 @@ +fields('n', array('status')) + ->condition('aid', $nodeid, '=') + ->execute() + ->fetchAll(); + + // If we don't have an entry as disabled (!empty()), AMP is enabled by default + if (isset($result[0]->status) && $result[0]->status == 0) { + $is_enabled = FALSE; + } + + return $is_enabled; +} + +/** + * Set a node as AMP disabled. + * + * @param $nodeid + * Node ID of the node to set as disabled. + * + * @return \DatabaseStatementInterface|int + * @throws \Exception + */ +function amp_db_disable_amp($nodeid) { + // Simply is enabled? + $query = db_select('amp_node', 'n'); + $query->condition('n.aid', $nodeid); + $query->addExpression('COUNT(*)'); + + $queryresults = $query->execute()->fetchField(); + + if ($queryresults > 0) { + // If the field already exists, just update it. + $aid = db_update('amp_node') + ->fields(array( + 'status' => AMP_DISABLED, + )) + ->condition('aid', $nodeid, '=') + ->execute(); + } + else { + // Otherwise, create a new one. + $aid = db_insert('amp_node') + ->fields(array( + 'aid' => $nodeid, + 'status' => AMP_DISABLED, + )) + ->execute(); + } + + return $aid; +} + +/** + * Set a node as AMP enabled. + * + * @param $nodeid + * Node ID of the node to set as enabled. + * + * @throws \Exception + */ +function amp_db_enable_amp($nodeid) { + // Enable removes the flag from the db. + amp_db_remove($nodeid); +} + +/** + * Remove a given node from AMP. + * + * @param $nodeid + * Node ID to remove. + * + * @throws \Exception + */ +function amp_db_remove($nodeid) { + // Deleting it from the table will set it up as enabled by default and will + // keep the table as small as possible. + db_delete('amp_node') + ->condition('aid', $nodeid) + ->execute(); +}