addtoany.module 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <?php
  2. /**
  3. * @file
  4. * Handle AddToAny integration.
  5. */
  6. use Drupal\Core\Entity\EntityInterface;
  7. use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
  8. use Drupal\Core\Render\Markup;
  9. use Drupal\Core\Url;
  10. use Drupal\Component\Utility\UrlHelper;
  11. use Drupal\node\Entity\Node;
  12. /**
  13. * Implements hook_theme().
  14. */
  15. function addtoany_theme() {
  16. return [
  17. 'addtoany_standard' => [
  18. 'variables' => [
  19. 'addtoany_html' => FALSE,
  20. 'link_url' => FALSE,
  21. 'link_title' => FALSE,
  22. 'buttons_size' => FALSE,
  23. 'button_setting' => FALSE,
  24. 'button_image' => FALSE,
  25. 'universal_button_placement' => FALSE,
  26. 'entity_type' => '',
  27. 'bundle' => '',
  28. ],
  29. ],
  30. ];
  31. }
  32. /**
  33. * Implements hook_theme_suggestions_HOOK().
  34. */
  35. function addtoany_theme_suggestions_addtoany_standard(array $variables) {
  36. $suggestion = 'addtoany_standard__';
  37. $suggestions = [];
  38. if (!empty($variables['entity_type'])) {
  39. $suggestion .= $variables['entity_type'];
  40. $suggestions[] = $suggestion;
  41. }
  42. if (!empty($variables['entity_type']) && !empty($variables['bundle'])) {
  43. $suggestion .= '__' . $variables['bundle'];
  44. $suggestions[] = $suggestion;
  45. }
  46. return $suggestions;
  47. }
  48. /**
  49. * Implements hook_entity_extra_field_info().
  50. */
  51. function addtoany_entity_extra_field_info() {
  52. $extra = [];
  53. $types = ['node', 'comment', 'media'];
  54. // Allow modules to alter the entity types.
  55. \Drupal::moduleHandler()->alter('addtoany_entity_types', $types);
  56. foreach ($types as $type) {
  57. $bundles = Drupal::service('entity_type.bundle.info')->getBundleInfo($type);
  58. foreach ($bundles as $bundle => $bundle_data) {
  59. $extra[$type][$bundle]['display']['addtoany'] = [
  60. 'label' => t('AddToAny'),
  61. 'description' => t('Share buttons by AddToAny'),
  62. 'weight' => 5,
  63. 'visible' => FALSE,
  64. ];
  65. }
  66. }
  67. return $extra;
  68. }
  69. /**
  70. * Implements hook_ENTITY_TYPE_view().
  71. */
  72. function addtoany_entity_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  73. if ($display->getComponent('addtoany')) {
  74. $data = addtoany_create_entity_data($entity);
  75. $build['addtoany'] = [
  76. '#addtoany_html' => \Drupal::token()->replace($data['addtoany_html'], ['node' => $entity]),
  77. '#link_url' => $data['link_url'],
  78. '#link_title' => $data['link_title'],
  79. '#button_setting' => $data['button_setting'],
  80. '#button_image' => $data['button_image'],
  81. '#universal_button_placement' => $data['universal_button_placement'],
  82. '#buttons_size' => $data['buttons_size'],
  83. '#entity_type' => $entity->getEntityType()->id(),
  84. '#bundle' => $entity->bundle(),
  85. '#theme' => 'addtoany_standard',
  86. ];
  87. }
  88. }
  89. /**
  90. * Implements hook_page_attachments().
  91. */
  92. function addtoany_page_attachments(&$page) {
  93. $config = \Drupal::config('addtoany.settings');
  94. // Initial JavaScript.
  95. $additional_js = $config->get('additional_js');
  96. if (\Drupal::moduleHandler()->moduleExists('token')) {
  97. $node = \Drupal::routeMatch()->getParameter('node');
  98. $data = [];
  99. if ($node) {
  100. if (is_numeric($node)) {
  101. $node = Node::load($node);
  102. }
  103. $data = ['node' => $node];
  104. $additional_js = \Drupal::token()->replace($additional_js, $data);
  105. }
  106. }
  107. $javascript_header = 'window.a2a_config=window.a2a_config||{};'
  108. . 'a2a_config.callbacks=[];a2a_config.overlays=[];'
  109. . 'a2a_config.templates={};'
  110. . (($config->get('no_3p')) ? 'a2a_config.no_3p=1;' : '')
  111. . $additional_js;
  112. // Add AddToAny initial JS config.
  113. $page['#attached']['html_head'][] = [
  114. // The data.
  115. [
  116. // Add a <script> tag.
  117. '#tag' => 'script',
  118. // Add JavaScript to the <script> tag.
  119. '#value' => Markup::create($javascript_header),
  120. // Give weight so it appears after meta tags, etc.
  121. '#weight' => 10,
  122. ],
  123. // Assign a key to reference this HTML <HEAD> element when altering.
  124. 'addtoany-js',
  125. ];
  126. // Custom CSS.
  127. $css = $config->get('additional_css');
  128. if (!empty($css)) {
  129. // Add AddToAny custom CSS.
  130. $page['#attached']['html_head'][] = [
  131. // The data.
  132. [
  133. // Add a <style> tag.
  134. '#tag' => 'style',
  135. // Add CSS to the <style> tag.
  136. '#value' => $css,
  137. // Give weight so it appears after meta tags, etc.
  138. '#weight' => 10,
  139. ],
  140. // Assign a key to reference this HTML <HEAD> element when altering.
  141. 'addtoany-css',
  142. ];
  143. }
  144. // Add module's main library, which includes external AddToAny core JS,
  145. // and the module's CSS.
  146. $page['#attached']['library'][] = 'addtoany/addtoany';
  147. }
  148. /**
  149. * Generate data for AddToAny buttons for a node.
  150. *
  151. * @param object $node
  152. * The node object to create the buttons for.
  153. * @param object $config
  154. * If present this will be used as custom config data. Use NULL for default
  155. * config data.
  156. *
  157. * @return array
  158. * The array with url, title, additional_html that will be send to Twig.
  159. */
  160. function addtoany_create_entity_data($node, $config = NULL) {
  161. $url = isset($node) ? $node->url('canonical', ['absolute' => TRUE]) : NULL;
  162. $title = isset($node) ? $node->label() : NULL;
  163. return addtoany_create_data($url, $title, $config);
  164. }
  165. /**
  166. * Generate data for AddToAny buttons.
  167. *
  168. * @param string $url
  169. * If present this will be used as the URL.
  170. * @param string $title
  171. * If present this will be used as the title. Use an empty string for no title
  172. * or NULL to use the current page title.
  173. * @param object $config
  174. * If present this will be used as custom config data. Use NULL for default
  175. * config data.
  176. *
  177. * @return array
  178. * The array with url, title, additional_html that will be send to Twig.
  179. */
  180. function addtoany_create_data($url = NULL, $title = NULL, $config = NULL) {
  181. if (is_null($config)) {
  182. $config = \Drupal::config('addtoany.settings');
  183. }
  184. $additional_html = rtrim($config->get('additional_html'));
  185. $universal_button_placement = $config->get('universal_button_placement');
  186. $is_front = \Drupal::service('path.matcher')->isFrontPage();
  187. // Default to <front> or the current path.
  188. if (!isset($url)) {
  189. // Use <front> for the front page to avoid '/node' as the final URL,
  190. // otherwise use current path.
  191. $url = ($is_front) ? Url::fromRoute('<front>')
  192. ->setAbsolute()
  193. ->toString() : Url::fromRoute('<current>')->setAbsolute()->toString();
  194. }
  195. else {
  196. // Sanitize and encode URL for HTML output.
  197. $url = UrlHelper::stripDangerousProtocols($url);
  198. }
  199. // Default to the current title if available, otherwise use the site name.
  200. if (!isset($title)) {
  201. $site_name = \Drupal::config('system.site')->get('name');
  202. if ($is_front) {
  203. $title = $site_name;
  204. }
  205. else {
  206. $request = \Drupal::request();
  207. $route_match = \Drupal::routeMatch();
  208. $title = \Drupal::service('title_resolver')
  209. ->getTitle($request, $route_match->getRouteObject());
  210. // Expecting array|string|null from getTitle.
  211. if (is_array($title)) {
  212. $title['#allowed_tags'] = [];
  213. $title = \Drupal::service('renderer')->renderPlain($title);
  214. }
  215. }
  216. $title = (empty($title)) ? $site_name : $title;
  217. }
  218. $buttons_size = $config->get('buttons_size');
  219. // Must be a 3 digit positive integer.
  220. $buttons_size = (
  221. $buttons_size !== '32' && strlen($buttons_size) <= 3 && $buttons_size !== ''
  222. && is_numeric($buttons_size) && intval($buttons_size) == $buttons_size && $buttons_size > 0
  223. ) ? $buttons_size : '32';
  224. $button_setting = $config->get('universal_button');
  225. if ($button_setting == 'custom') {
  226. $button_image = UrlHelper::stripDangerousProtocols($config->get('custom_universal_button'));
  227. }
  228. $info = [
  229. 'link_url' => $url,
  230. 'link_title' => $title,
  231. 'buttons_size' => $buttons_size,
  232. 'button_setting' => $button_setting,
  233. 'button_image' => isset($button_image) ? $button_image : '',
  234. 'universal_button_placement' => $universal_button_placement,
  235. 'addtoany_html' => $additional_html,
  236. ];
  237. return $info;
  238. }