Removed legacy display types. Redesigned the config page.
[project/addthis.git] / classes / AddThis.php
index ee07bd4..36a79ff 100644 (file)
 /**
  * @file
  * An AddThis-class.
- *
- * @author Jani Palsamäki
  */
 
 class AddThis {
 
   const BLOCK_NAME = 'addthis_block';
-  const DEFAULT_FORMATTER = 'addthis_default';
+  const DEFAULT_CUSTOM_CONFIGURATION_CODE = 'var addthis_config = {}';
+  const DEFAULT_FORMATTER = 'addthis_default_formatter';
+  const DEFAULT_NUMBER_OF_PREFERRED_SERVICES = 4;
+  const FIELD_TYPE = 'addthis';
   const MODULE_NAME = 'addthis';
+  const PERMISSION_ADMINISTER_ADDTHIS = 'administer addthis';
+  const PERMISSION_ADMINISTER_ADVANCED_ADDTHIS = 'administer advanced addthis';
   const STYLE_KEY = 'addthis_style';
+  const WIDGET_TYPE = 'addthis_button_widget';
 
   // AddThis attribute and parameter names (as defined in AddThis APIs)
   const PROFILE_ID_QUERY_PARAMETER = 'pubid';
   const TITLE_ATTRIBUTE = 'addthis:title';
+  const URL_ATTRIBUTE = 'addthis:url';
 
   // Persistent variable keys
+  const ADDRESSBOOK_ENABLED_KEY = 'addthis_addressbook_enabled';
   const BLOCK_WIDGET_TYPE_KEY = 'addthis_block_widget_type';
   const BOOKMARK_URL_KEY = 'addthis_bookmark_url';
+  const CLICKBACK_TRACKING_ENABLED_KEY = 'addthis_clickback_tracking_enabled';
+  const CLICK_TO_OPEN_COMPACT_MENU_ENABLED_KEY = 'addthis_click_to_open_compact_menu_enabled';
+  const CO_BRAND_KEY = 'addthis_co_brand';
+  const COMPLIANT_508_KEY = 'addthis_508_compliant';
+  const CUSTOM_CONFIGURATION_CODE_ENABLED_KEY = 'addthis_custom_configuration_code_enabled';
+  const CUSTOM_CONFIGURATION_CODE_KEY = 'addthis_custom_configuration_code';
   const ENABLED_SERVICES_KEY = 'addthis_enabled_services';
+  const OPEN_WINDOWS_ENABLED_KEY = 'addthis_open_windows_enabled';
   const PROFILE_ID_KEY = 'addthis_profile_id';
   const SERVICES_CSS_URL_KEY = 'addthis_services_css_url';
   const SERVICES_JSON_URL_KEY = 'addthis_services_json_url';
+  const STANDARD_CSS_ENABLED_KEY = 'addthis_standard_css_enabled';
+  const UI_DELAY_KEY = 'addthis_ui_delay';
+  const UI_HEADER_BACKGROUND_COLOR_KEY = 'addthis_ui_header_background_color';
+  const UI_HEADER_COLOR_KEY = 'addthis_ui_header_color';
   const WIDGET_JS_URL_KEY = 'addthis_widget_js_url';
+  const WIDGET_JS_ASYNC = 'addthis_widget_async';
 
   // External resources
   const DEFAULT_BOOKMARK_URL = 'http://www.addthis.com/bookmark.php?v=250';
-  const DEFAULT_SERVICES_JSON_URL = 'http://cache.addthiscdn.com/services/v1/sharing.en.json';
   const DEFAULT_SERVICES_CSS_URL = 'http://cache.addthiscdn.com/icons/v1/sprites/services.css';
+  const DEFAULT_SERVICES_JSON_URL = 'http://cache.addthiscdn.com/services/v1/sharing.en.json';
   const DEFAULT_WIDGET_JS_URL = 'http://s7.addthis.com/js/250/addthis_widget.js';
+  const DEFAULT_WIDGET_JS_ASYNC = TRUE;
 
   // Internal resources
   const ADMIN_CSS_FILE = 'addthis.admin.css';
-  const ADMIN_INCLUDE_FILE = 'addthis.admin.inc';
+  const ADMIN_INCLUDE_FILE = 'includes/addthis.admin.inc';
 
   // Widget types
-  const WIDGET_TYPE_COMPACT_BUTTON = 'compact_button';
-  const WIDGET_TYPE_DISABLED = 'disabled';
-  const WIDGET_TYPE_LARGE_BUTTON = 'large_button';
-  const WIDGET_TYPE_TOOLBOX = 'toolbox';
-  const WIDGET_TYPE_SHARECOUNT = 'sharecount';
-
-  // Markup constants
-  const AMP_ENTITY = '&';
-  const HASH = '#';
-  const HREF = 'href';
-
-  public static function getWidgetTypes() {
+  const WIDGET_TYPE_DISABLED = 'addthis_disabled';
+
+  // Styles
+  const CSS_32x32 = 'addthis_32x32_style';
+
+  private static $instance;
+
+  /* @var AddThisJson */
+  private $json;
+
+  /**
+   * @return AddThis
+   */
+  public static function getInstance() {
+    if (!isset(self::$instance)) {
+      $addThis = new AddThis();
+      $addThis->setJson(new AddThisJson());
+      self::$instance = $addThis;
+    }
+    return self::$instance;
+  }
+
+  public function setJson(AddThisJson $json) {
+    $this->json = $json;
+  }
+
+  /*
+   * Get all the DisplayTypes that are available.
+   */
+  public function getDisplayTypes() {
     return array(
       self::WIDGET_TYPE_DISABLED => t('Disabled'),
-      self::WIDGET_TYPE_COMPACT_BUTTON => t('Compact button'),
-      self::WIDGET_TYPE_LARGE_BUTTON => t('Large button'),
-      self::WIDGET_TYPE_TOOLBOX => t('Toolbox'),
-      self::WIDGET_TYPE_SHARECOUNT => t('Sharecount'),
     );
+    // @todo Get all display types available and
+    // provide a array with their names.
   }
 
-  public static function getBlockWidgetType() {
-    return variable_get(self::BLOCK_WIDGET_TYPE_KEY, self::WIDGET_TYPE_COMPACT_BUTTON);
-  }
-
-  public static function getWidgetMarkup($widgetType = '', $entity = NULL) {
-    switch ($widgetType) {
-      case self::WIDGET_TYPE_LARGE_BUTTON:
-        $markup =
-          '<a class="addthis_button" '
-          . self::getAddThisAttributesMarkup($entity)
-          . MarkupGenerator::generateAttribute(self::HREF, self::getFullBookmarkUrl())
-          . '><img src="http://s7.addthis.com/static/btn/v2/lg-share-en.gif" width="125" height="16" alt="'
-          . t('Bookmark and Share')
-          . '" style="border:0"/></a>'
-          . self::getWidgetScriptElement();
-        break;
-      case self::WIDGET_TYPE_COMPACT_BUTTON:
-        $markup =
-          '<a class="addthis_button" '
-          . self::getAddThisAttributesMarkup($entity)
-          . MarkupGenerator::generateAttribute(self::HREF, self::getFullBookmarkUrl())
-          . '><img src="http://s7.addthis.com/static/btn/sm-share-en.gif" width="83" height="16" alt="'
-          . t('Bookmark and Share')
-          . '" style="border:0"/></a>'
-          . self::getWidgetScriptElement();
-        break;
-      case self::WIDGET_TYPE_TOOLBOX:
-        $markup =
-          '<div class="addthis_toolbox addthis_default_style"><a '
-          . MarkupGenerator::generateAttribute(self::HREF, self::getFullBookmarkUrl())
-          . ' class="addthis_button_compact" '
-          . self::getAddThisAttributesMarkup($entity)
-          . '>'
-          . t('Share')
-          . '</a><span class="addthis_separator">|</span>' 
-          . '<a class="addthis_button_preferred_1" '
-          . self::getAddThisAttributesMarkup($entity)
-          . '></a>'
-          . '<a class="addthis_button_preferred_2" '
-          . self::getAddThisAttributesMarkup($entity)
-          . '></a>'
-          . '<a class="addthis_button_preferred_3" '
-          . self::getAddThisAttributesMarkup($entity)
-          . '></a>'
-          . '<a class="addthis_button_preferred_4" '
-          . self::getAddThisAttributesMarkup($entity)
-          . '></a></div>'
-          . self::getWidgetScriptElement();
-        break;
-      case self::WIDGET_TYPE_SHARECOUNT:
-        $markup =
-          '<div class="addthis_toolbox addthis_default_style"><a class="addthis_counter" '
-          . self::getAddThisAttributesMarkup($entity)
-          . '></a></div>'
-          . self::getWidgetScriptElement();
-        break;
-      default:
-        $markup = '';
-        break;
+  /*
+   * Return me the markup for a certain display type.
+   *
+   * Variables contains #entity and #settings as keys when applicable.
+   * When #entity is not there we link to the current url. When #settings
+   * is not there we use the default settings.
+   */
+  public function getDisplayMarkup($display, $options = array()) {
+    $formatters = addthis_field_info_formatter_field_type();
+
+    // When we have the entity and entity_type we can send it to the url.
+    if (isset($options['#entity']) && isset($options['#entity_type'])) {
+      // See if we can create the url and send it through a hook so others
+      // can play with it.
+      $uri = entity_uri($options['#entity_type'], $options['#entity']);
+      $uri['options'] += array(
+        'absolute' => TRUE,
+      );
+      // Add hook here to alter the uri maybe also based on fields from the
+      // entity. Like a custom share link. Pass $options and $uri. Return
+      // a uri object to which we can reset it. Maybe use the alter structure.
+
+      $options['#url'] = url($uri['path'], $uri['options']);
     }
-    return $markup;
-  }
+    // @todo Hash the options array and cache the markup.
+    // This will save all the extra calls to modules and alters.
 
-  public static function getProfileId() {
-    return variable_get(AddThis::PROFILE_ID_KEY);
-  }
+    // Give other module the option to alter our markup options.
+    drupal_alter('addthis_markup_options', $options);
 
-  public static function getServicesCssUrl() {
-    return variable_get(AddThis::SERVICES_CSS_URL_KEY, self::DEFAULT_SERVICES_CSS_URL);
-  }
+    $markup = array(
+      '#display' => $options['#display'],
+    );
+    if (array_key_exists($display, $formatters)) {
+      // The display type is found. Now get it and get the markup.
+      $display_inf = $formatters[$display];
 
-  public static function getServicesJsonUrl() {
-    return variable_get(AddThis::SERVICES_JSON_URL_KEY, self::DEFAULT_SERVICES_JSON_URL);
-  }
+      // Get all hook implementation to verify later if we can call it.
+      $implementations = module_implements('addthis_display_markup');
 
-  public static function getServiceOptions() {
-    return self::getServices();
-  }
+      // First we look for a targeted implementation to call.
+      if (function_exists($display_inf['module'] . '_addthis_display_markup__' . $display)) {
+        $markup += call_user_func_array($display_inf['module'] . '_addthis_display_markup__' . $display, array($options));
 
-  public static function getEnabledServiceOptions() {
-    return self::getEnabledServices();
+        // This should be the default implementation that is called.
+      }
+      elseif (in_array($display_inf['module'], $implementations)) {
+        $markup += module_invoke($display_inf['module'], 'addthis_display_markup', $display, $options);
+      }
+      // Give other module the option to later our markup.
+      drupal_alter('addthis_markup', $markup);
+      return $markup;
+
+    }
+    else {
+      // Return empty
+      return array();
+    }
+    // If no display is found or something went wrong we go here.
+    return array();
   }
 
-  public static function addStylesheets() {
-    drupal_add_css(self::getServicesCssUrl(), 'external');
-    drupal_add_css(self::getAdminCssFilePath(), 'file');
+  /*
+   * Get the type DisplayType used for our AddThis block.
+   */
+  public function getBlockDisplayType() {
+    return variable_get(self::BLOCK_WIDGET_TYPE_KEY, self::WIDGET_TYPE_DISABLED);
   }
 
-  public static function addConfigurationOptionsJs() {
-    $enabledServices = self::getServiceNamesAsCommaSeparatedString();
-    drupal_add_js("var addthis_config = {services_compact: '" . $enabledServices . "more'}", 'inline');
+  public function getProfileId() {
+    return check_plain(variable_get(AddThis::PROFILE_ID_KEY));
   }
 
-  private static function getServiceNamesAsCommaSeparatedString() {
-    $enabledServiceNames = array_values(self::getEnabledServices());
-    $enabledServicesAsCommaSeparatedString = '';
-    foreach ($enabledServiceNames as $enabledServiceName) {
-      if ($enabledServiceName != '0') {
-        $enabledServicesAsCommaSeparatedString .= $enabledServiceName . ',';
-      }
-    }
-    return $enabledServicesAsCommaSeparatedString;
+  public function getServicesCssUrl() {
+    return check_url(variable_get(AddThis::SERVICES_CSS_URL_KEY, self::DEFAULT_SERVICES_CSS_URL));
   }
 
-  private static function getAdminCssFilePath() {
-    return drupal_get_path('module', self::MODULE_NAME) . '/' . self::ADMIN_CSS_FILE;
+  public function getServicesJsonUrl() {
+    return check_url(variable_get(AddThis::SERVICES_JSON_URL_KEY, self::DEFAULT_SERVICES_JSON_URL));
   }
 
-  private static function getServices() {
+  public function getServices() {
     $rows = array();
-    $json = new Json();
-    $services = $json->decode(self::getServicesJsonUrl());
-    if ($services != NULL) {
-      foreach ($services['data'] AS $service) {
+    $services = $this->json->decode($this->getServicesJsonUrl());
+    if (empty($services)) {
+      drupal_set_message(t('AddThis services could not be loaded from ' . $this->getServicesJsonUrl()), 'warning');
+    }
+    else {
+      foreach ($services['data'] as $service) {
         $serviceCode = check_plain($service['code']);
         $serviceName = check_plain($service['name']);
         $rows[$serviceCode] = '<span class="addthis_service_icon icon_' . $serviceCode . '"></span> ' . $serviceName;
@@ -180,51 +190,231 @@ class AddThis {
     return $rows;
   }
 
-  private static function getEnabledServices() {
+  public function getEnabledServices() {
     return variable_get(self::ENABLED_SERVICES_KEY, array());
   }
 
-  public static function getBaseBookmarkUrl() {
-    return variable_get(self::BOOKMARK_URL_KEY, self::DEFAULT_BOOKMARK_URL);
+  public function getWidgetJsAsync() {
+    return variable_get(self::WIDGET_JS_ASYNC, self::DEFAULT_WIDGET_JS_ASYNC);
+  }
+
+  public function addStylesheets() {
+    drupal_add_css($this->getServicesCssUrl(), 'external');
+    drupal_add_css($this->getAdminCssFilePath(), 'file');
   }
 
-  private static function getFullBookmarkUrl() {
-    return self::getBaseBookmarkUrl() . self::getProfileIdQueryParameterPrefixedWithAmp();
+  public function addWidgetJs() {
+    // Define if we load async or not.
+    $url = self::getWidgetUrl() . (self::getWidgetJsAsync() ? '?async=1' : '');
+    if (self::getWidgetJsAsync()) {
+      drupal_add_js(
+        array(
+        'addthis' => array(
+          'widget_url' => $url,
+        ),
+      ),
+        'setting'
+      );
+    }
+    else {
+      // Add AddThis.com resources
+      drupal_add_js(
+        $url,
+        array(
+        'type' => 'external',
+        'group' => JS_LIBRARY,
+        'every_page' => TRUE,
+        'weight' => 9,
+      )
+      );
+    }
+    // Add local internal behaviours
+    if (self::getWidgetJsAsync()) {
+      drupal_add_js(
+        drupal_get_path('module', 'addthis') . '/addthis.js',
+        array(
+        'group' => JS_DEFAULT,
+        'weight' => 10,
+        'every_page' => TRUE,
+        'preprocess' => TRUE,
+      )
+      );
+    }
   }
 
-  public static function getBaseWidgetJsUrl() {
-    return variable_get(self::WIDGET_JS_URL_KEY, self::DEFAULT_WIDGET_JS_URL);
+  public function addConfigurationOptionsJs() {
+    if ($this->isCustomConfigurationCodeEnabled()) {
+      $javascript = $this->getCustomConfigurationCode();
+    }
+    else {
+      $enabledServices = $this->getServiceNamesAsCommaSeparatedString() . 'more';
+
+      global $language;
+      $configuration = array(
+        'services_compact' => $enabledServices,
+        'data_track_clickback' => $this->isClickbackTrackingEnabled(),
+        'ui_508_compliant' => $this->get508Compliant(),
+        'ui_click' => $this->isClickToOpenCompactMenuEnabled(),
+        'ui_cobrand' => $this->getCoBrand(),
+        'ui_delay' => $this->getUiDelay(),
+        'ui_header_background' => $this->getUiHeaderBackgroundColor(),
+        'ui_header_color' => $this->getUiHeaderColor(),
+        'ui_open_windows' => $this->isOpenWindowsEnabled(),
+        'ui_use_css' => $this->isStandardCssEnabled(),
+        'ui_use_addressbook' => $this->isAddressbookEnabled(),
+        'ui_language' => $language->language,
+      );
+      drupal_alter('addthis_configuration', $configuration);
+
+      $javascript = 'var addthis_config = ' . drupal_json_encode($configuration);
+    }
+    drupal_add_js(
+      $javascript,
+      array(
+      'type' => 'inline',
+      'scope' => 'footer',
+      'every_page' => TRUE,
+    )
+    );
   }
 
-  private static function getProfileIdQueryParameter($prefix) {
-    $profileId = self::getProfileId();
-    return $profileId != NULL ? $prefix . self::PROFILE_ID_QUERY_PARAMETER . '=' . $profileId : '';
+  public function isClickToOpenCompactMenuEnabled() {
+    return (boolean) variable_get(self::CLICK_TO_OPEN_COMPACT_MENU_ENABLED_KEY, FALSE);
   }
 
-  private static function getProfileIdQueryParameterPrefixedWithAmp() {
-    return self::getProfileIdQueryParameter(self::AMP_ENTITY);
+  public function isOpenWindowsEnabled() {
+    return (boolean) variable_get(self::OPEN_WINDOWS_ENABLED_KEY, FALSE);
   }
 
-  private static function getProfileIdQueryParameterPrefixedWithHash() {
-    return self::getProfileIdQueryParameter(self::HASH);
+  public function getUiDelay() {
+    return (int) check_plain(variable_get(self::UI_DELAY_KEY));
   }
 
-  private static function getAddThisAttributesMarkup($entity) {
-    if (is_object($entity)) {
-      return self::getAddThisTitleAttributeMarkup($entity) . ' ';
+  public function getUiHeaderColor() {
+    return check_plain(variable_get(self::UI_HEADER_COLOR_KEY));
+  }
+
+  public function getUiHeaderBackgroundColor() {
+    return check_plain(variable_get(self::UI_HEADER_BACKGROUND_COLOR_KEY));
+  }
+
+  public function isStandardCssEnabled() {
+    return (boolean) variable_get(self::STANDARD_CSS_ENABLED_KEY, TRUE);
+  }
+
+  public function getCustomConfigurationCode() {
+    return variable_get(self::CUSTOM_CONFIGURATION_CODE_KEY, self::DEFAULT_CUSTOM_CONFIGURATION_CODE);
+  }
+
+  public function isCustomConfigurationCodeEnabled() {
+    return (boolean) variable_get(self::CUSTOM_CONFIGURATION_CODE_ENABLED_KEY, FALSE);
+  }
+
+  public function getBaseWidgetJsUrl() {
+    return check_url(variable_get(self::WIDGET_JS_URL_KEY, self::DEFAULT_WIDGET_JS_URL));
+  }
+
+  public function getBaseBookmarkUrl() {
+    return check_url(variable_get(self::BOOKMARK_URL_KEY, self::DEFAULT_BOOKMARK_URL));
+  }
+
+  public function getCoBrand() {
+    return variable_get(self::CO_BRAND_KEY, '');
+  }
+
+  public function get508Compliant() {
+    return (boolean) variable_get(self::COMPLIANT_508_KEY, FALSE);
+  }
+
+  public function isClickbackTrackingEnabled() {
+    return (boolean) variable_get(self::CLICKBACK_TRACKING_ENABLED_KEY, FALSE);
+  }
+
+  public function isAddressbookEnabled() {
+    return (boolean) variable_get(self::ADDRESSBOOK_ENABLED_KEY, FALSE);
+  }
+
+  /**
+   * Define the following object in the $optoins.
+   *
+   * #entity_type
+   * #entity
+   * #url
+   */
+  public function getAddThisAttributesMarkup($options) {
+    if (isset($options)) {
+      $attributes = array();
+
+      // Add title
+      if (isset($options['#entity'])) {
+        $attributes += $this->getAttributeTitle($options['#entity']);
+      }
+      $attributes += $this->getAttributeUrl($options);
+
+      // Return the array with attributes
+      return $attributes;
+    }
+    return array();
+  }
+
+  private function getAttributeTitle($entity) {
+    if (isset($entity->title)) {
+      return array(
+        self::TITLE_ATTRIBUTE => (check_plain($entity->title)  . ' - ' . variable_get('site_name')),
+      );
     }
-    return '';
+    return array();
+  }
+
+  private function getAttributeUrl($options) {
+    if (isset($options['#url'])) {
+      return array(
+        self::URL_ATTRIBUTE => $options['#url'],
+      );
+    }
+    return array();
+  }
+
+  public function getLargeButtonsClass() {
+    return $this->areLargeIconsEnabled() ? ' addthis_32x32_style ' : '';
+  }
+
+  private function getServiceNamesAsCommaSeparatedString() {
+    $enabledServiceNames = array_values($this->getEnabledServices());
+    $enabledServicesAsCommaSeparatedString = '';
+    foreach ($enabledServiceNames as $enabledServiceName) {
+      if ($enabledServiceName != '0') {
+        $enabledServicesAsCommaSeparatedString .= $enabledServiceName . ',';
+      }
+    }
+    return $enabledServicesAsCommaSeparatedString;
+  }
+
+  private function getAdminCssFilePath() {
+    return drupal_get_path('module', self::MODULE_NAME) . '/' . self::ADMIN_CSS_FILE;
+  }
+
+  /*
+   * Helper function. Get a bookmark url appended with the ProfileId
+   */
+  public function getFullBookmarkUrl() {
+    return $this->getBaseBookmarkUrl() . $this->getProfileIdQueryParameterPrefixedWithAmp();
+  }
+
+  private function getProfileIdQueryParameter($prefix) {
+    $profileId = $this->getProfileId();
+    return !empty($profileId) ? $prefix . self::PROFILE_ID_QUERY_PARAMETER . '=' . $profileId : '';
   }
 
-  private static function getAddThisTitleAttributeMarkup($entity) {
-    return MarkupGenerator::generateAttribute(self::TITLE_ATTRIBUTE, drupal_get_title() . ' - ' . check_plain($entity->title));
+  private function getProfileIdQueryParameterPrefixedWithAmp() {
+    return $this->getProfileIdQueryParameter('&');
   }
 
-  private static function getWidgetScriptElement() {
-    return '<script type="text/javascript" src="' . self::getWidgetUrl() . '"></script>';
+  private function getProfileIdQueryParameterPrefixedWithHash() {
+    return $this->getProfileIdQueryParameter('#');
   }
 
-  private static function getWidgetUrl() {
-    return self::getBaseWidgetJsUrl() . self::getProfileIdQueryParameterPrefixedWithHash();
+  private function getWidgetUrl() {
+    return check_url($this->getBaseWidgetJsUrl() . $this->getProfileIdQueryParameterPrefixedWithHash());
   }
 }