You are here

google_plusone.module in Google Plus One Button | Google+ Badge 6

Same filename and directory in other branches
  1. 7 google_plusone.module

File

google_plusone.module
View source
<?php

/**
 * Implements hook_menu().
 */
function google_plusone_menu() {
  $items['admin/settings/google-plusone'] = array(
    'title' => 'Google +1 Button',
    'description' => 'Configure Google Plus One button settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'google_plusone_admin_settings',
    ),
    'access arguments' => array(
      'administer google plusone',
    ),
    'file' => 'google_plusone.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_theme().
 */
function google_plusone_theme() {
  return array(
    'google_plusone_button' => array(
      'arguments' => array(
        'node' => NULL,
        'url' => NULL,
        'css' => '',
        'size' => '',
        'syntax' => 'HTML5',
        'annotation' => 'theme',
        'width' => '250',
        'alias' => 'aliased',
      ),
    ),
    'google_plusone_badge' => array(
      'arguments' => array(
        'style' => 'badge',
        'syntax' => 'HTML5',
      ),
    ),
  );
}

/**
 * Implements hook_perm().
 */
function google_plusone_perm() {
  $perms[] = 'administer google plusone';
  $perms[] = 'view google plusone';
  return $perms;
}

/**
 * Implements hook_nodeapi().
 */
function google_plusone_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  $node_types = variable_get('google_plusone_node_types', array());
  if ($op === 'view' && !empty($node_types[$node->type]) && user_access('view google plusone') && $node->build_mode === NODE_BUILD_NORMAL) {
    $locations = variable_get('google_plusone_node_location', array(
      'full',
    ));
    $view_mode = $a3 ? 'teaser' : 'full';
    if (!empty($locations[$view_mode]) && empty($locations['link'])) {
      $default = array(
        'annotation' => 'bubble',
        'width' => '250',
        'size' => '',
        // standard
        'css' => 'margin: 0 1em 1em 1em;float:right',
        'syntax' => 'HTML5',
        'alias' => 'aliased',
      );
      $button_settings = array_merge($default, variable_get('google_plusone_button_settings', array()));
      $button_settings['node'] = $node;
      $node->content['google_plusone'] = array(
        '#weight' => variable_get('google_plusone_weight', -5),
        '#value' => theme('google_plusone_button', $button_settings),
      );
    }
  }
}

/**
 * Implements hook_link().
 * Add a button tag to the link section of the node (teaser or full node).
 */
function google_plusone_link($type, $node = NULL, $teaser = FALSE) {
  $links = array();
  $view_mode = $teaser ? 'teaser' : 'full';
  $locations = variable_get('google_plusone_node_location', array(
    'full',
  ));
  $node_types = variable_get('google_plusone_node_types', array());
  if ($type === 'node' && !empty($locations['link']) && !empty($locations[$view_mode]) && !empty($node_types[$node->type]) && user_access('view google plusone')) {
    $default = array(
      'annotation' => 'bubble',
      'width' => '250',
      'size' => '',
      // standard
      'css' => 'margin: 0 1em 1em 1em;float:right;',
      'syntax' => 'HTML5',
    );
    $button_settings = variable_get('google_plusone_button_settings', $default) + array(
      'node' => $node,
    );
    $links['google_plusone'] = array(
      'title' => theme('google_plusone_button', $button_settings),
      'html' => TRUE,
    );
  }
  return $links;
}

/**
 * Returns HTML for the Google +1 button.
 *
 * @param $variables
 *   An associative array containing:
 *   - syntax: (optional) A string. If contains 'g:plusone' will be used that syntax. Otherwise, HTML5 syntax by default.
 *   - url: (optional) A string containing the URL to use in the button, or '<front>' (language-aware)
 *                     or leaving it empty, the URL will be deducted on-the-fly by Google.
 *   - node: (optional) The node object. (Only will be use its nid)
 *   - size:  (optional) A string 'small', 'medium', 'standard' (default), 'tall'
 *   - annotation: (optional) A string 'none', 'bubble' (default), 'inline'
 *   - width: (optional) An integer to indicate width of button in case of inline annotation. Default 250
 *   - css: (optional) A string with inline CSS rules for the wrapper.
 *
 * @ingroup themeable
 */
function theme_google_plusone_button($variables) {
  google_plusone_add_js();

  // URL negotiation
  $url = '';
  if (!empty($variables['node']->nid)) {
    if ($variables['alias'] === 'aliased') {
      $url = url('node/' . $variables['node']->nid, array(
        'absolute' => TRUE,
      ));
    }
    else {
      $url = url('node/' . $variables['node']->nid, array(
        'absolute' => TRUE,
        'alias' => TRUE,
      ));
    }
  }
  elseif (!empty($variables['url'])) {

    // See block settings to understand the 'url' setting
    if ($variables['url'] === '<front>') {
      $url = url('', array(
        'absolute' => TRUE,
      ));

      // language-aware
    }
    else {
      $url = check_url($variables['url']);
    }
  }

  // Rendering attributes and tags.
  $syntax = isset($variables['syntax']) ? $variables['syntax'] : '';
  $data = $syntax === 'g:plusone' ? '' : 'data-';

  // HTML5 valid attributes must have 'data-' prefix
  $url = empty($url) ? '' : $data . 'href="' . $url . '" ';
  $size = empty($variables['size']) ? '' : $data . 'size="' . check_plain($variables['size']) . '" ';
  $annotation = empty($variables['annotation']) ? '' : $data . 'annotation="' . check_plain($variables['annotation']) . '" ';
  $width = empty($variables['width']) ? '' : $data . 'width="' . check_plain($variables['width']) . '" ';
  $tag_start = $syntax === 'g:plusone' ? '<g:plusone ' : '<div class="g-plusone" ';
  $tag_end = $syntax === 'g:plusone' ? '></g:plusone>' : '></div>';

  // Putting it all together
  $button = $tag_start . $url . $size . $annotation . $width . $tag_end;

  // Wrap it and serve it
  if ($variables['css'] !== 'nowrapper') {
    $css = empty($variables['css']) ? '' : 'style="' . check_plain($variables['css']) . '"';
    $button = '<div class="g-plusone-wrapper" ' . $css . ' >' . $button . '</div>';
  }
  return $button;
}

/**
 * Returns HTML for the Google +1 badge.
 *
 * @param $variables
 *   An associative array containing:
 *   - syntax: (optional) A string 'badge', 'smallbadge', 'smallicon', 'mediumicon', 'largeicon'
 *
 * @ingroup themeable
 */
function theme_google_plusone_badge($settings) {
  google_plusone_add_js();
  $page_id = variable_get('google_plusone_badge_page_id', '');
  $size = 16;

  // 'smallicon'
  // Any other edge-case
  switch ($settings['style']) {
    case 'badge':
    case 'smallbadge':
      $syntax = 'HTML5';

      // todo: provide option in block settings.
      $tag_start = $syntax === 'g:plus' ? '<g:plus ' : '<div class="g-plus"';
      $tag_end = $syntax === 'g:plus' ? '></g:plus>' : '></div>';
      $badge = $tag_start . ' data-href="' . check_url($page_id) . '" data-size="' . check_plain($settings['style']) . '"' . $tag_end;
      return $badge;
    case 'smallicon':
      $size = 16;
      break;
    case 'mediumicon':
      $size = 32;
      break;
    case 'largeicon':
      $size = 64;
      break;
  }
  $badge = '<a href="' . check_url($page_id) . '/?prsrc=3" style="text-decoration: none;"><img src="https://ssl.gstatic.com/images/icons/gplus-' . $size . '.png" width="' . $size . '" height="' . $size . '" style="border: 0;"/></a>';
  return $badge;
}

/**
 * Add the external Google +1 JavaScript that will render the buttons.
 */
function google_plusone_add_js() {
  static $js_added;

  // Adds only once the main script.
  if ($js_added) {
    return;
  }
  $default_advanced = array(
    'lang' => '',
    'scope_location' => 'footer',
    'parsetags' => 'onload',
    'async' => 1,
  );
  $config = array_merge($default_advanced, variable_get('google_plusone_advanced_settings', array()));
  $script_options = array();
  if (!empty($config['lang'])) {
    $lang = google_plusone_button_negotiate_language($config['lang']);
    $script_options[] = 'lang:"' . $lang . '"';
  }
  if ($config['parsetags'] !== 'onload') {
    $script_options[] = 'parsetags:"' . $config['parsetags'] . '"';
  }
  if ($config['async']) {
    $script = empty($script_options) ? '' : "window.___gcfg = {" . implode(',', $script_options) . "};";
    $script .= "(function() {";
    $script .= "var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;";
    $script .= "po.src = 'https://apis.google.com/js/plusone.js';";
    $script .= "var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);";
    $script .= "})();";
    drupal_add_js($script, 'inline', $config['scope_location']);
  }
  else {
    $script = '<script type="text/javascript" src="https://apis.google.com/js/plusone.js">';
    $script .= empty($script_options) ? '' : '{' . implode(',', $script_options) . '}';
    $script .= '</script>';
    drupal_set_html_head($script);
  }
  $js_added = TRUE;
}

/**
 * Returns an appropriated language code.
 * If there is only one language codes in the admin settings, it will return that.
 * If there are multiple ones, the language code returned is based on the current global $language variable.
 *
 * There are some edge cases where Drupal language codes doesn't match
 * with the ones used by Google +1 API. See:
 *
 *    *_locale_get_predefined_list() function in 'includes/locale.inc'
 *    * http://code.google.com/apis/+1button/#languages
 *
 * @param  $glanguages A string of lower-case language codes separated by commas.
 *                     Example: es,fr,pt-br,he
 *
 * @return A Google +1 compatible language Code (string)
 *         or empty string. In this last case, Google will use 'en-US' language by default.
 *
 */
function google_plusone_button_negotiate_language($glanguages = array()) {
  global $language;
  $current_code = $language->language;
  $glanguages = explode(",", $glanguages);
  if (count($glanguages) === 1) {
    return $glanguages[0];
  }

  /* Note that Drupal uses lower-case language codes and in_array is case sensitive.
   * That's why in the submit hook of the admin settings form
   * the language codes contained in $glanguages are lower-case'd.
   */
  if (in_array($current_code, $glanguages, TRUE)) {
    return $current_code;
  }

  // Any other edge-case
  switch (drupal_substr($current_code, 0, 2)) {
    case 'en':
      return $current_code === 'en' ? 'en-US' : 'en-GB';
    case 'zh':
      return $current_code === 'zh-hans' ? 'zh-CN' : 'zh-TW';
    case 'he':
      return 'iw';
    case 'es':
      return 'es-419';

    // if didn't match before with 'es', then only other option is 'es-419'
    case 'nn':
      return 'no';
    case 'pt':
      return 'pt-PT';
    default:
      return '';
  }
}

/**
 * Implements hook_block().
 */
function google_plusone_block($op = 'list', $delta = 0, $edit = array()) {
  $default = array(
    'annotation' => 'bubble',
    'width' => '250',
    'url' => '',
    'size' => '',
    // standard
    'css' => 'text-align:center;',
    'alias' => 'aliased',
  );
  $blocks['google_plusone_badge_block'] = array(
    'info' => t('Google Plus One +1 Badge'),
    'cache' => BLOCK_NO_CACHE,
  );
  switch ($op) {
    case 'list':
      $blocks[0]['info'] = t('Google +1 Button');
      $blocks[0]['cache'] = BLOCK_NO_CACHE;
      $blocks[1]['info'] = t('Google +1 Badge');
      $blocks[1]['cache'] = BLOCK_NO_CACHE;
      return $blocks;
      break;
    case 'view':
      if (user_access('view google plusone')) {
        google_plusone_add_js();
        $block = array();
        switch ($delta) {
          case 0:
            $default = array(
              'url' => '',
              'annotation' => 'bubble',
              'width' => '250',
              'size' => '',
              // standard
              'css' => 'text-align:center;',
              'alias' => 'aliased',
            );
            $button_settings = array_merge($default, variable_get('google_plusone_button_settings', array()));
            $settings = array_merge($button_settings, variable_get('google_plusone_block_settings', array()));
            $block['subject'] = NULL;
            $block['content'] = theme('google_plusone_button', $settings);
            return $block;
          case 1:
            $page_id = variable_get('google_plusone_badge_page_id', '');
            drupal_set_html_head('<link src="' . check_url($page_id) . '" rel="publisher" />');
            $style = variable_get('google_plusone_badge_style', 'badge');
            $block['subject'] = NULL;
            $block['content'] = theme('google_plusone_badge', array(
              'style' => $style,
            ));
            return $block;
        }
      }
      break;
    case 'configure':
      module_load_include('inc', 'google_plusone', 'google_plusone.admin');

      // Custom javascript code to preview in real-time the button
      drupal_add_js(drupal_get_path('module', 'google_plusone') . '/google_plusone.admin.js');

      // not good performance in <head>, but anyway, it's only for the admin page and can help for debugging purposes.
      $script = '<script type="text/javascript" src="http://apis.google.com/js/plusone.js">';
      drupal_set_html_head('<script type="text/javascript" src="http://apis.google.com/js/plusone.js"></script>');
      $form = array();
      if ($delta == 0) {
        $settings = array_merge($default, variable_get('google_plusone_block_settings', array()));
        $available_sizes = array(
          'small' => t('Small (15px)'),
          'medium' => t('Medium (20px)'),
          '' => t('Standard (24px)'),
          'tall' => t('Tall (60px)'),
        );
        $available_annotations = array(
          'none' => t('None'),
          'bubble' => t('Bubble (by default)'),
          'inline' => t('Inline'),
        );
        $form['g1button'] = array(
          '#type' => 'fieldset',
          '#title' => t('Button Settings'),
          '#description' => t('Notice that these settings are exclusively for this block and they cover only some options.<br />The rest of settings will be taken from the <a href="@sett">general settings</a>.', array(
            '@sett' => url('admin/settings/google-plusone'),
          )),
        );
        $form['g1button']['google_plusone_block_url'] = array(
          '#title' => t('URL address to use for Google +1 button'),
          '#type' => 'textfield',
          '#default_value' => $settings['url'],
          '#description' => t('3 different options: <br/><ol><li>Type an fixed, absolute URL. Remember to type the <em>http://</em> part.</li><li>Type <em>&lt;front&gt;</em></front> to use always your frontpage ($base_url), that is language-aware. </li><li>Leave empty. Then it will be used the current URL address present in that moment in that page where the block is.</li></ol>'),
        );
        $form['g1button']['google_plusone_block_alias'] = array(
          '#type' => 'radios',
          '#title' => t('Aliased node path'),
          '#default_value' => $settings['alias'],
          '#options' => array(
            'not_aliased' => t('Not aliased'),
            'aliased' => t('Aliased'),
          ),
          '#description' => t('By default aliased. It only will be applied when the previous setting <em>URL</em> has been left empty and it\'s a node page. <br/> If you change this setting, <strong>be aware</strong> that Google+ will see them as different URLs, so the button will not keep the previous counting.'),
        );
        $form['g1button']['google_plusone_block_annotation'] = array(
          '#type' => 'radios',
          '#title' => t('Annotation: How to show the counting?'),
          '#options' => $available_annotations,
          '#default_value' => $settings['annotation'],
          '#description' => google_plusone_build_preview_button($available_sizes),
        );
        $form['g1button']['google_plusone_block_width'] = array(
          '#type' => 'textfield',
          '#title' => t('Width (only affects to inline annotation)'),
          '#default_value' => $settings['width'],
          '#size' => 20,
          '#description' => t('By default recommended 250 (pixels). Minimum 120'),
        );
        $form['g1button']['google_plusone_block_size'] = array(
          '#type' => 'radios',
          '#title' => t('Size'),
          '#options' => $available_sizes,
          '#default_value' => $settings['size'],
        );
        $form['g1button']['google_plusone_block_wrapper_css'] = array(
          '#type' => 'textfield',
          '#title' => t('Optional wrapper with CSS'),
          '#maxlength' => 256,
          '#default_value' => $settings['css'],
          '#description' => t('To help with the layout and placement of the button, it will be rendered by default wrapped in a div: 	&lt;div class="g-plusone-wrapper"&gt;	&lt;/div&gt;<br/>You can enter CSS rules to style this wrapper. By default <em>text-align:center</em><br />To disable totally the wrapper, input the word <em>nowrapper</em>'),
        );
      }
      elseif ($delta == 1) {
        $available_styles = array(
          'badge' => t('Standard Badge'),
          'smallbadge' => t('Small Badge'),
          'smallicon' => t('Small Icon'),
          'mediumicon' => t('Medium Icon'),
          'largeicon' => t('Large Icon'),
          'no_badge' => t('No Badge'),
        );
        $form['g1badge'] = array(
          '#type' => 'fieldset',
          '#title' => t('Badge Settings'),
          '#description' => t('Notice that these settings are exclusively for this block and they cover the basic options.<br /> The rest of settings will be taken from the <a href="@sett">general settings</a>.', array(
            '@sett' => url('admin/config/services/google-plusone'),
          )),
        );
        $form['g1badge']['google_plusone_badge_page_id'] = array(
          '#title' => t('URL address to use in the Google +1 button'),
          '#type' => 'textfield',
          '#default_value' => variable_get('google_plusone_badge_page_id', ''),
          '#description' => t('Copy and paste here the whole URL of your page, including the <em>https://</em> part.<br /> For example: https://plus.google.com/u/0/101560853443212199687'),
        );
        $form['g1badge']['google_plusone_badge_style'] = array(
          '#title' => t('URL address to use in the Google +1 button'),
          '#type' => 'radios',
          '#options' => $available_styles,
          '#default_value' => variable_get('google_plusone_badge_style', 'badge'),
          '#description' => t('Choose the style of badge. Preview the styles <a href="@preview" target="_blank">in the Google Developers site</a>', array(
            '@preview' => 'https://developers.google.com/+/plugins/badge/preview',
          )),
        );
      }
      return $form;
    case 'save':
      module_load_include('inc', 'google_plusone', 'google_plusone.admin');
      if ($delta == 0) {
        $settings = array(
          'url' => $edit['google_plusone_block_url'],
          'annotation' => $edit['google_plusone_block_annotation'],
          'width' => $edit['google_plusone_block_width'],
          'size' => $edit['google_plusone_block_size'],
          'css' => google_plusone_trim($edit['google_plusone_block_wrapper_css'], ';'),
          'alias' => $edit['google_plusone_block_alias'],
        );
        variable_set('google_plusone_block_settings', $settings);
      }
      elseif ($delta == 1) {
        variable_set('google_plusone_badge_page_id', check_url(google_plusone_trim($edit['google_plusone_badge_page_id'], '/')));
        variable_set('google_plusone_badge_style', $edit['google_plusone_badge_style']);
      }
  }
}

Functions

Namesort descending Description
google_plusone_add_js Add the external Google +1 JavaScript that will render the buttons.
google_plusone_block Implements hook_block().
google_plusone_button_negotiate_language Returns an appropriated language code. If there is only one language codes in the admin settings, it will return that. If there are multiple ones, the language code returned is based on the current global $language variable.
google_plusone_link Implements hook_link(). Add a button tag to the link section of the node (teaser or full node).
google_plusone_menu Implements hook_menu().
google_plusone_nodeapi Implements hook_nodeapi().
google_plusone_perm Implements hook_perm().
google_plusone_theme Implements hook_theme().
theme_google_plusone_badge Returns HTML for the Google +1 badge.
theme_google_plusone_button Returns HTML for the Google +1 button.