diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8cdb845..0000000 --- a/LICENSE +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {description} - Copyright (C) {year} {fullname} - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - {signature of Ty Coon}, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. - diff --git a/README.md b/README.md index 80f90f6..20a9390 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,62 @@ -# addthis -Port AddThis to D8 + +-- SUMMARY -- + +Add This module provides Drupal integration to addthis.com link sharing service. +Integration has been implemented as a field. + +Description from addthis.com: +The AddThis button spreads your content across the Web by making it easier for +your visitors to bookmark and share it with other people, again... and again... +and again. This simple yet powerful button is very easy to install and provides +valuable Analytics about the bookmarking and sharing activity of your users. +AddThis helps your visitors create a buzz for your site and increase its +popularity and ranking. + +AddThis is already on hundreds of thousands of websites including SAP, +TIME Magazine, Oracle, Freewebs, Entertainment Weekly, Topix, Lonely Planet, +MapQuest, MySpace, PGA Tour, Tower Records, Squidoo, Zappos, Funny or Die, FOX, +ABC, CBS, Glamour, PostSecret, WebMD, American Idol, and ReadWriteWeb, +just to name a few. Each month our button is displayed 20 billion times. + +-- REQUIREMENTS -- + +Field, Block + +-- INSTALLATION -- + +Normal Drupal module installation, see http://drupal.org/node/70151 for further +information. + +For link sharing statistics registration at http://addthis.com/ is required, but +the module will work even without registration. + +-- INCLUDED MODULES -- +1. **addthis** - Provides the base API to integrate with AddThis. Also creates RenderElements, +base Twig templates and global admin settings for AddThis. Does not provide any +rendering functionality on its own. +2. **addthis_block** - Provides a configurable block for displaying AddThis. +3. **addthis_fields** - Provides two field formatters for AddThis to allow for rendering on +entities. + +-- CONFIGURATION -- + +Use the admin configuration page to configure settings and see http://drupal.org/node/1309922 +for a walkthrough on how to configure the rest. + +-- DEVELOPMENT -- + +Please see the addthis.api.php for implementation options of different displays +and altering configuration on rendering. + +-- CONTACT -- + +Current D8 contributors +* John Doyle (doylejd) - https://www.drupal.org/u/doylejd + +Current D7 maintainers: +* Vesa Palmu (wesku) - http://drupal.org/user/75070 +* Jani Palsamäki (janip) - http://drupal.org/user/1356218 +* Matthias Glastra (matglas86) - http://drupal.org/user/573464 + +Major contributions by: +Lesmana Lim (lesmana) - http://drupal.org/user/84263 diff --git a/README.txt b/README.txt deleted file mode 100644 index 709d22c..0000000 --- a/README.txt +++ /dev/null @@ -1,51 +0,0 @@ - --- SUMMARY -- - -Add This module provides Drupal integration to addthis.com link sharing service. -Integration has been implemented as a field. - -Description from addthis.com: -The AddThis button spreads your content across the Web by making it easier for -your visitors to bookmark and share it with other people, again... and again... -and again. This simple yet powerful button is very easy to install and provides -valuable Analytics about the bookmarking and sharing activity of your users. -AddThis helps your visitors create a buzz for your site and increase its -popularity and ranking. - -AddThis is already on hundreds of thousands of websites including SAP, -TIME Magazine, Oracle, Freewebs, Entertainment Weekly, Topix, Lonely Planet, -MapQuest, MySpace, PGA Tour, Tower Records, Squidoo, Zappos, Funny or Die, FOX, -ABC, CBS, Glamour, PostSecret, WebMD, American Idol, and ReadWriteWeb, -just to name a few. Each month our button is displayed 20 billion times. - --- REQUIREMENTS -- - -Field, Block - --- INSTALLATION -- - -Normal Drupal module installation, see http://drupal.org/node/70151 for further -information. - -For link sharing statistics registration at http://addthis.com/ is required, but -the module will work even without registration. - --- CONFIGURATION -- - -Use the admin configuration page to configure settings and see http://drupal.org/node/1309922 -for a walkthrough on how to configure the rest. - --- DEVELOPMENT -- - -Please see the addthis.api.php for implementation options of different displays -and altering configuration on rendering. - --- CONTACT -- - -Current maintainers: -* Vesa Palmu (wesku) - http://drupal.org/user/75070 -* Jani Palsamäki (janip) - http://drupal.org/user/1356218 -* Matthias Glastra (matglas86) - http://drupal.org/user/573464 - -Major contributions by: -Lesmana Lim (lesmana) - http://drupal.org/user/84263 diff --git a/addthis.libraries.yml b/addthis.libraries.yml new file mode 100644 index 0000000..2b0ff77 --- /dev/null +++ b/addthis.libraries.yml @@ -0,0 +1,15 @@ +addthis.admin: + version: VERSION + css: + theme: + http://cache.addthiscdn.com/icons/v1/sprites/services.css: {} + css/addthis.admin.css: {} + +addthis.widget: + version: VERSION + js: + js/addthis.js: {} + dependencies: + - core/jquery + - core/drupal + - core/drupalSettings diff --git a/addthis.links.menu.yml b/addthis.links.menu.yml index f35fea7..86a6d3a 100644 --- a/addthis.links.menu.yml +++ b/addthis.links.menu.yml @@ -1,5 +1,12 @@ addthis.settings: - title: AddThis + title: AddThis - Basic Settings description: 'Manage your site''s AddThis settings.' parent: system.admin_config_ui - route_name: addthis.settings \ No newline at end of file + route_name: addthis.settings + weight: 1 +addthis.settings.advanced: + title: AddThis - Advanced Settings + description: 'Manage your site''s advanced AddThis settings.' + parent: system.admin_config_ui + route_name: addthis.settings.advanced + weight: 2 \ No newline at end of file diff --git a/addthis.links.task.yml b/addthis.links.task.yml new file mode 100644 index 0000000..bd96cb5 --- /dev/null +++ b/addthis.links.task.yml @@ -0,0 +1,8 @@ +addthis.settings: + title: 'Basic' + route_name: addthis.settings + base_route: addthis.settings +addthis.settings.advanced: + title: 'Advanced' + route_name: addthis.settings.advanced + base_route: addthis.settings \ No newline at end of file diff --git a/addthis.module b/addthis.module index a4abe2d..02c123e 100644 --- a/addthis.module +++ b/addthis.module @@ -1,2 +1,17 @@ [ + 'render element' => 'element', + ], + 'addthis_basic_toolbox' => [ + 'render element' => 'element', + ], + ]; +} + + diff --git a/addthis.permissions.yml b/addthis.permissions.yml new file mode 100644 index 0000000..dbd85af --- /dev/null +++ b/addthis.permissions.yml @@ -0,0 +1,6 @@ +administer addthis settings: + title: 'Administer AddThis Settings' + description: 'Perform configuration tasks for AddThis.' +administer advanced addthis settings: + title: 'Administer Advanced AddThis Settings' + description: 'Perform advanced configuration tasks for AddThis.' \ No newline at end of file diff --git a/addthis.routing.yml b/addthis.routing.yml index 6556c6b..825b5db 100644 --- a/addthis.routing.yml +++ b/addthis.routing.yml @@ -4,4 +4,11 @@ addthis.settings: _form: '\Drupal\addthis\Form\AddThisSettingsForm' _title: 'AddThis' requirements: - _permission: 'administer site configuration' \ No newline at end of file + _permission: 'administer addthis settings' +addthis.settings.advanced: + path: '/admin/config/user-interface/addthis/advanced' + defaults: + _form: '\Drupal\addthis\Form\AddThisSettingsAdvancedForm' + _title: 'AddThis Advanced Settings' + requirements: + _permission: 'administer advanced addthis settings' \ No newline at end of file diff --git a/addthis.services.yml b/addthis.services.yml new file mode 100644 index 0000000..1b81925 --- /dev/null +++ b/addthis.services.yml @@ -0,0 +1,5 @@ +services: + # This service creates a more complex access check. + addthis.script_manager: + class: Drupal\addthis\AddThisScriptManager + arguments: ['@language_manager', '@config.factory'] diff --git a/config/install/addthis.settings.advanced.yml b/config/install/addthis.settings.advanced.yml new file mode 100644 index 0000000..b1cd51c --- /dev/null +++ b/config/install/addthis.settings.advanced.yml @@ -0,0 +1,10 @@ +# TODO: remove prefix from these variables. Combine with addthis.settings.yml? +addthis_bookmark_url: 'http://www.addthis.com/bookmark.php?v=300' +addthis_services_css_url: 'http://cache.addthiscdn.com/icons/v1/sprites/services.css' +addthis_services_json_url: 'http://cache.addthiscdn.com/services/v1/sharing.en.json' +addthis_widget_js_url: 'http://s7.addthis.com/js/300/addthis_widget.js' +addthis_custom_configuration_code_enabled: FALSE +addthis_custom_configuration_code: 'var addthis_config = {}' +addthis_widget_load_domready: TRUE +addthis_widget_load_async: FALSE +addthis_widget_include: 2 \ No newline at end of file diff --git a/config/install/addthis.settings.yml b/config/install/addthis.settings.yml index 33a16e4..05904de 100644 --- a/config/install/addthis.settings.yml +++ b/config/install/addthis.settings.yml @@ -1,3 +1,4 @@ +#TODO: remove prefix from variables? compact_menu: menu_style: addthis_co_brand: '' diff --git a/config/schema/addthis.schema.yml b/config/schema/addthis.schema.yml index 46898cf..ca47f7b 100644 --- a/config/schema/addthis.schema.yml +++ b/config/schema/addthis.schema.yml @@ -12,24 +12,24 @@ addthis.settings: type: mapping label: 'Style' mapping: - addthis_co_brand: - type: string - label: 'Branding text' - addthis_ui_header_color: - type: string - label: 'Header text color' - addthis_ui_header_background_color: - type: string - label: 'Header background color' - addthis_click_to_open_compact_menu_enabled: - type: boolean - label: 'Open compact menu on click' - addthis_open_windows_enabled: - type: boolean - label: 'Use pop-up windows' - addthis_ui_delay: - type: string - label: 'Menu open delay' + addthis_co_brand: + type: string + label: 'Branding text' + addthis_ui_header_color: + type: string + label: 'Header text color' + addthis_ui_header_background_color: + type: string + label: 'Header background color' + addthis_click_to_open_compact_menu_enabled: + type: integer + label: 'Open compact menu on click' + addthis_open_windows_enabled: + type: integer + label: 'Use pop-up windows' + addthis_ui_delay: + type: string + label: 'Menu open delay' enabled_services: type: mapping label: 'Compact menu enabled services' @@ -65,7 +65,7 @@ addthis.settings: label: 'Services Excluded' analytics: type: mapping - label: 'Analytics & Tracking' + label: 'Analytics and Tracking' mapping: addthis_profile_id: type: string @@ -92,4 +92,71 @@ addthis.settings: addthis_twitter_template: type: string label: 'Template text' +addthis.settings.advanced: + type: mapping + label: 'AddThis Advanced Settings' + mapping: + addthis_bookmark_url: + type: string + label: 'Bookmark URL' + addthis_services_css_url: + type: string + label: 'Services CSS URL' + addthis_services_json_url: + type: string + label: 'Services JSON URL' + addthis_widget_js_url: + type: string + label: 'Widget JS URL' + addthis_custom_configuration_code_enabled: + type: boolean + label: 'Use custom AddThis configuration code' + addthis_custom_configuration_code: + type: string + label: 'AddThis custom configuration code' + addthis_widget_load_domready: + type: boolean + label: 'Load the AddThis resources after the DOM is ready' + addthis_widget_load_async: + type: boolean + label: 'Initialize asynchronously through addthis.init()' + addthis_widget_include: + type: integer + label: 'Load widget js.' +block.settings.addthis_block: + type: block_settings + label: 'AddThis Block Configuration' + mapping: + display_type: + type: string + label: 'Display Type' + basic_button: + type: mapping + label: 'Basic Button Block Settings' + mapping: + button_size: + type: string + label: 'Button Size' + extra_css: + type: string + label: 'Extra CSS' + basic_toolbox: + type: mapping + label: 'Basic Toolbox Block Settings' + mapping: + share_services: + type: string + label: 'Share Services' + buttons_size: + type: string + label: 'Button Size' + counter_orientation: + type: string + label: 'Counter Orientation' + extra_css: + type: string + label: 'Extra CSS' + + + diff --git a/css/addthis.admin.css b/css/addthis.admin.css new file mode 100644 index 0000000..818b0d7 --- /dev/null +++ b/css/addthis.admin.css @@ -0,0 +1,25 @@ +.addthis_service_icon { + display: inline-block; + padding-left: 20px; +} + +#edit-addthis-enabled-services .form-item, #edit-addthis-excluded-services .form-item { + float: left; + width: 20%; +} + +#edit-addthis-enabled-services .form-item .description { + clear: both; +} + +#edit-addthis-excluded-services label.option, +#edit-addthis-enabled-services label.option, +#edit-addthis-excluded-services .addthis_service_icon, +#edit-addthis-enabled-services .addthis_service_icon { + display: inline-block; +} + +#edit-addthis-excluded-services .addthis_service_icon, +#edit-addthis-enabled-services .addthis_service_icon { + margin-bottom: -1.5px; +} \ No newline at end of file diff --git a/js/addthis.js b/js/addthis.js new file mode 100644 index 0000000..f08e008 --- /dev/null +++ b/js/addthis.js @@ -0,0 +1,32 @@ +// AddThis requires a global variable + +var addthis_config, + addthis_share; + +(function ($, Drupal, window, document, undefined) { + Drupal.behaviors.addThisWidget = { + + //@TODO Need to support domready and async loading. See http://support.addthis.com/customer/portal/articles/1338006-url-parameters + + attach: function (context, settings) { + if (context === document) { // only fires on document load + + // Because we cannot dynamically add JS + if (typeof settings.addThisWidget.widgetScript !== 'undefined') { + $.getScript(settings.addThisWidget.widgetScript) + .done(function (script, textStatus) { + }).fail(function (jqxhr, settings, exception) { + // TODO: check for fail msg + }); + } + if (typeof settings.addThisWidget.config !== 'undefined') { + addthis_config = settings.addThisWidget.config; + } + if (typeof settings.addThisWidget.share !== 'undefined') { + addthis_share = settings.addThisWidget.share; + } + } + } + }; + +})(jQuery, Drupal, this, this.document); diff --git a/src/AddThis.php b/src/AddThis.php deleted file mode 100644 index baee5c8..0000000 --- a/src/AddThis.php +++ /dev/null @@ -1,249 +0,0 @@ -setJson(new AddThisJson()); - $add_this->setConfig(); - self::$instance = $add_this; - } - - return self::$instance; - } - - /** - * Set the json object. - */ - public function setJson(AddThisJson $json) { - $this->json = $json; - } - - public function setConfig(){ - $this->config = \Drupal::config('addthis.settings'); - } - - - - public function getServices() { - $rows = array(); - $services = $this->json->decode($this->getServicesJsonUrl()); - if (empty($services)) { - drupal_set_message(t('AddThis services could not be loaded from @service_url', array('@service_url', $this->getServicesJsonUrl())), 'warning'); - } - else { - foreach ($services['data'] as $service) { - $serviceCode = SafeMarkup::checkPlain($service['code']); - $serviceName = SafeMarkup::checkPlain($service['name']); - $rows[$serviceCode] = ' ' . $serviceName; - } - } - return $rows; - } - - /** - * Get the type used for the block. - */ - public function getBlockDisplayType() { - $block_widget_type = $this->config->get(self::BLOCK_WIDGET_TYPE_KEY); - $block_widget_type = isset($block_widget_type) ? $block_widget_type : self::WIDGET_TYPE_DISABLED; - return $block_widget_type; - } - - /** - * Get the settings used by the block display. - */ - public function getBlockDisplaySettings() { - $block_widget_settings = $this->config->get(self::BLOCK_WIDGET_SETTINGS_KEY); - $block_widget_settings = isset($block_widget_settings) ? $block_widget_settings : NULL; - $settings = $block_widget_settings; - - if ($settings == NULL && $this->getBlockDisplayType() != self::WIDGET_TYPE_DISABLED) { - $settings = \Drupal::service('plugin.manager.field.formatter')->getDefinition($this->getBlockDisplayType()); - } - - return $settings; - } - - - public function getServicesCssUrl() { - $services_css_url_key = $this->config->get(self::SERVICES_CSS_URL_KEY); - $services_css_url_key = isset($services_css_url_key) ? $services_css_url_key : self::DEFAULT_SERVICES_CSS_URL; - return check_url($services_css_url_key); - } - - public function getServicesJsonUrl() { - $service_json_url_key = $this->config->get(self::SERVICES_JSON_URL_KEY); - $service_json_url_key = isset($service_json_url_key) ? $service_json_url_key : self::DEFAULT_SERVICES_JSON_URL; - return check_url($service_json_url_key); - } - - - - /** - * Return the type of inclusion. - * - * @return string - * Retuns domready or async. - */ - public function getWidgetJsInclude() { - $widget_js_include = $this->config->get(self::WIDGET_JS_INCLUDE); - $widget_js_include = isset($widget_js_include) ? $widget_js_include : self::DEFAULT_WIDGET_JS_INCLUDE; - return $widget_js_include; - } - - /** - * Return if domready loading should be active. - * - * @return bool - * Returns TRUE if domready is enabled. - */ - public function getWidgetJsDomReady() { - $widget_js_load_domready = $this->config->get(self::WIDGET_JS_LOAD_DOMREADY); - $widget_js_load_domready = isset($widget_js_load_domready) ? $widget_js_load_domready : self::DEFAULT_WIDGET_JS_LOAD_DOMREADY; - return $widget_js_load_domready; - } - - /** - * Return if async initialization should be active. - * - * @return bool - * Returns TRUE if async is enabled. - */ - public function getWidgetJsAsync() { - $widget_js_load_async = $this->config->get(self::WIDGET_JS_LOAD_ASYNC); - $widget_js_load_async = isset($widget_js_load_async) ? $widget_js_load_async : self::DEFAULT_WIDGET_JS_LOAD_ASYNC; - return $widget_js_load_async; - } - - - public function getCustomConfigurationCode() { - $custom_configuration_code = $this->config->get(self::CUSTOM_CONFIGURATION_CODE_KEY); - $custom_configuration_code = isset($custom_configuration_code) ? $custom_configuration_code : self::DEFAULT_CUSTOM_CONFIGURATION_CODE; - return $custom_configuration_code; - } - - public function isCustomConfigurationCodeEnabled() { - $custom_configuration_code_enabled = $this->config->get(self::CUSTOM_CONFIGURATION_CODE_ENABLED_KEY); - $custom_configuration_code_enabled = isset($custom_configuration_code_enabled) ? $custom_configuration_code_enabled : FALSE; - - return (boolean) $custom_configuration_code_enabled; - } - - public function getBaseWidgetJsUrl() { - $widget_js_url = $this->config->get(self::WIDGET_JS_URL_KEY); - $widget_js_url = isset($widget_js_url) ? $widget_js_url : self::DEFAULT_WIDGET_JS_URL; - return check_url($widget_js_url); - } - - public function getBaseBookmarkUrl() { - $bookmark_url = $this->config->get(self::BOOKMARK_URL_KEY); - $bookmark_url = isset($bookmark_url) ? $bookmark_url : self::DEFAULT_BOOKMARK_URL; - return check_url($bookmark_url); - } - - - public function addStylesheets() { - drupal_add_css($this->getServicesCssUrl(), 'external'); - drupal_add_css($this->getAdminCssFilePath(), 'file'); - } - - 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 function getProfileIdQueryParameterPrefixedWithAmp() { - return $this->getProfileIdQueryParameter('&'); - } - - private function getProfileIdQueryParameterPrefixedWithHash() { - return $this->getProfileIdQueryParameter('#'); - } - - -} \ No newline at end of file diff --git a/src/AddThisBasicButtonFormTrait.php b/src/AddThisBasicButtonFormTrait.php new file mode 100644 index 0000000..67987db --- /dev/null +++ b/src/AddThisBasicButtonFormTrait.php @@ -0,0 +1,62 @@ + 'small', + 'extra_css' => '', + ]; + } + + /** + * Returns partial configuration form for the AddThisBasicButton. + * + * @param $parent_class - The class that is requesting the form. + * @param $options - The base configuration for the class. (Block/Field) + * + * @return array - Partial form to provide configuration. + */ + protected function addThisBasicButtonForm($options){ + $element = []; + + $element['button_size'] = [ + '#title' => t('Image'), + '#type' => 'select', + '#default_value' => $options['button_size'], + '#options' => [ + 'small' => t('Small'), + 'big' => t('Big'), + ], + ]; + $element['extra_css'] = [ + '#title' => t('Extra CSS declaration'), + '#type' => 'textfield', + '#size' => 40, + '#default_value' => $options['extra_css'], + '#description' => t('Specify extra CSS classes to apply to the button'), + ]; + + return $element; + } + + + +} \ No newline at end of file diff --git a/src/AddThisBasicToolboxFormTrait.php b/src/AddThisBasicToolboxFormTrait.php new file mode 100644 index 0000000..15a6c23 --- /dev/null +++ b/src/AddThisBasicToolboxFormTrait.php @@ -0,0 +1,114 @@ + 'facebook,twitter', + 'buttons_size' => 'addthis_16x16_style', + 'counter_orientation' => 'horizontal', + 'extra_css' => '', + ]; + } + + /** + * Returns partial configuration form for the AddThisBasicToolbox. + * + * @param $parent_class - The class that is requesting the form. + * @param $options - The base configuration for the class. (Block/Field) + * + * @return array - Partial form to provide configuration. + */ + protected function addThisBasicToolboxForm($options){ + $element = []; + + $element['share_services'] = [ + '#title' => t('Services'), + '#type' => 'textfield', + '#size' => 80, + '#default_value' => $options['share_services'], + '#required' => TRUE, + //Validate function is defined in addthis.module. + '#element_validate' => [ + get_class() . '::addThisDisplayElementServicesValidate' + ], + '#description' => + t('Specify the names of the sharing services and seperate them with a , (comma). The names on this list are valid.') . + t('Elements that are available but not ont the services list are (!services).', + ['!services' => 'bubble_style, pill_style, tweet, facebook_send, twitter_follow_native, google_plusone, stumbleupon_badge, counter_* (several supported services), linkedin_counter'] + ), + ]; + $element['buttons_size'] = [ + '#title' => t('Buttons size'), + '#type' => 'select', + '#default_value' => $options['buttons_size'], + '#options' => [ + 'addthis_16x16_style' => t('Small (16x16)'), + 'addthis_32x32_style' => t('Big (32x32)'), + ], + ]; + $element['counter_orientation'] = [ + '#title' => t('Counter orientation'), + '#description' => t('Specify the way service counters are oriented.'), + '#type' => 'select', + '#default_value' => $options['counter_orientation'], + '#options' => [ + 'horizontal' => t('Horizontal'), + 'vertical' => t('Vertical'), + ] + ]; + $element['extra_css'] = [ + '#title' => t('Extra CSS declaration'), + '#type' => 'textfield', + '#size' => 40, + '#default_value' => $options['extra_css'], + '#description' => t('Specify extra CSS classes to apply to the toolbox'), + ]; + + return $element; + } + + + /** + * @TODO Find out why this is never being called. + * + * Validation for services for BasicToolbox. + * @param array $element + * @param FormStateInterface $form_state + */ + public static function addThisDisplayElementServicesValidate($element, $form_state) { + $bad = FALSE; + + $services = trim($element['#value']); + $services = str_replace(' ', '', $services); + + if (!preg_match('/^[a-z\_\,0-9]+$/', $services)) { + $bad = TRUE; + } + // @todo Validate the service names against AddThis.com. Give a notice when there are bad names. + + // Return error. + if ($bad) { + $form_state->setErrorByName($element['#title'], t('The declared services are incorrect or nonexistent.')); + } + } + +} \ No newline at end of file diff --git a/src/AddThisScriptManager.php b/src/AddThisScriptManager.php new file mode 100644 index 0000000..0529381 --- /dev/null +++ b/src/AddThisScriptManager.php @@ -0,0 +1,238 @@ +language_manager = $languageManager; + $this->config_factory = $configFactory; + } + + /** + * Set values for addthis_config based on Sharing API documentation. See + * http://support.addthis.com/customer/portal/articles/1337994-the-addthis_config-variable + * for more details. + * + * @TODO Allow alter of 'addthis_configuration'. + * + * @todo Add static cache. + * + * @todo Make the adding of configuration dynamic. + * SRP is lost here. + */ + public function getAddThisConfig() { + $config = $this->config_factory->get('addthis.settings'); + + $enabled_services = $this->getServiceNamesAsCommaSeparatedString($config->get('compact_menu.enabled_services.addthis_enabled_services')) . 'more'; + $excluded_services = $this->getServiceNamesAsCommaSeparatedString($config->get('excluded_services.addthis_excluded_services')); + + $configuration = [ + 'services_compact' => $enabled_services, + 'services_exclude' => $excluded_services, + //'services_expanded' => @todo - add this + 'ui_508_compliant' => $config->get('compact_menu.additionals.addthis_508_compliant'), + 'ui_click' => $config->get('compact_menu.menu_style.addthis_click_to_open_compact_menu_enabled'), + 'ui_cobrand' => $config->get('compact_menu.menu_style.addthis_co_brand'), + 'ui_delay' => $config->get('compact_menu.menu_style.addthis_ui_delay'), + 'ui_header_background' => $config->get('compact_menu.menu_style.addthis_ui_header_background_color'), + 'ui_header_color' => $config->get('compact_menu.menu_style.addthis_ui_header_color'), + 'ui_open_windows' => $config->get('compact_menu.menu_style.addthis_open_windows_enabled'), + 'ui_use_css' => $config->get('compact_menu.additionals.addthis_standard_css_enabled'), + 'ui_use_addressbook' => $config->get('compact_menu.additionals.addthis_addressbook_enabled'), + 'ui_language' => $this->language_manager->getCurrentLanguage()->getId(), + 'pubid' => $config->get('analytics.addthis_profile_id'), + 'data_track_clickback' => $config->get('analytics.addthis_clickback_tracking_enabled'), + + ]; + + //Ensure that the Google Analytics module is enabled for tracking. + if (\Drupal::moduleHandler()->moduleExists('google_analytics')) { + if ($config->get('analytics.addthis_google_analytics_tracking_enabled')) { + $configuration['data_ga_property'] = $this->config_factory->get('google_analytics.settings') + ->get('account'); + $configuration['data_ga_social'] = $config->get('analytics.addthis_google_analytics_social_tracking_enabled'); + } + } + + return $configuration; + } + + /** + * Get a array with all addthis_share values that we set. More documentation can + * be found here: http://support.addthis.com/customer/portal/articles/1337996-the-addthis_share-variable + * + * @TODO Allow alter of 'addthis_configuration_share'. + * + * @todo Add static cache. + * + * @todo Make the adding of configuration dynamic. + * SRP is lost here. + */ + public function getAddThisShareConfig() { + $config = $this->config_factory->get('addthis.settings'); + + $addthis_share['templates']['twitter'] = $config->get('third_party.addthis_twitter_template'); + + return $addthis_share; + } + + /** + * Returns a comma separated list of service values. + * + * @param $services + * @return string + */ + protected function getServiceNamesAsCommaSeparatedString($services) { + $serviceNames = array_values($services); + $servicesAsCommaSeparatedString = ''; + foreach ($serviceNames as $serviceName) { + if ($serviceName != '0') { + $servicesAsCommaSeparatedString .= $serviceName . ','; + } + } + return $servicesAsCommaSeparatedString; + } + + /** + * Get an array containing the rendered AddThis services. + * + * @return array + * An array containing the rendered AddThis services. + */ + public function getServices() { + $rows = array(); + $json = new AddThisJson(); + $services = $json->decode($this->getServicesJsonUrl()); + if (empty($services)) { + drupal_set_message(t('AddThis services could not be loaded from @service_url', array( + '@service_url', + $this->getServicesJsonUrl() + )), 'warning'); + } + else { + foreach ($services['data'] as $service) { + $serviceCode = SafeMarkup::checkPlain($service['code']); + $serviceName = SafeMarkup::checkPlain($service['name']); + $service = array( + '#type' => 'inline_template', + '#template' => ' ' . $serviceName, + ); + //#options expects a string, not an array. Render the element so it becomes a string. + $rows[$serviceCode] = render($service); + } + } + return $rows; + } + + /** + * Gets the AddThis services url. + * + * @return string + */ + public function getServicesJsonUrl() { + $config = $this->config_factory->get('addthis.settings.advanced'); + $service_json_url_key = $config->get('addthis_services_json_url'); + $service_json_url_key = isset($service_json_url_key) ? $service_json_url_key : 'http://cache.addthiscdn.com/services/v1/sharing.en.json'; + return Html::escape(UrlHelper::stripDangerousProtocols($service_json_url_key)); + } + + /** + * Attach the widget js to the element. + * + * @todo Change the scope of the addthis.js. + * See if we can get the scope of the addthis.js into the header + * just below the settings so that the settings can be used in the loaded + * addthis.js of our module. + * + * @param array $element + * The element to attach the JavaScript to. + */ + public function attachJsToElement(&$element) { + $config = $this->config_factory->get('addthis.settings'); + $adv_config = $this->config_factory->get('addthis.settings.advanced'); + + //Generate AddThisWidgetURL + $fragment = []; + + $pubid = $config->get('analytics.addthis_profile_id'); + if (isset($pubid) && !empty($pubid) && is_string($pubid)) { + $fragment[] = 'pubid=' . $pubid; + } + + if ($adv_config->get('addthis_widget_load_async')) { + $fragment[] = 'async=1'; + } + + //Always load the script with domready flag. + $fragment[] = 'domready=1'; + + + $element['#attached']['library'][] = 'addthis/addthis.widget'; + $addThisConfig = $this->getAddThisConfig(); + $addThisShareConfig = $this->getAddThisShareConfig(); + + + + $options = [ + 'fragment' => implode('&', $fragment), + 'external' => TRUE, + ]; + + + $widget_url = $adv_config->get('addthis_widget_js_url'); + $widgetURL = URL::fromUri($widget_url, $options)->toString(); + + + $element['#attached']['drupalSettings']['addThisWidget'] = [ + 'widgetScript' => $widgetURL, + 'config' => $addThisConfig, + 'share' => $addThisShareConfig, + ]; + + + } + + +} + + + diff --git a/src/Element/AddThisBasicButton.php b/src/Element/AddThisBasicButton.php new file mode 100644 index 0000000..9f7c5ec --- /dev/null +++ b/src/Element/AddThisBasicButton.php @@ -0,0 +1,55 @@ + 'addthis_basic_button', + '#size' => 'addthis_16x16_style', + '#extra_classes' => '', + '#pre_render' => [ + [$class, 'preRender'], + ], + ]; + } + + public static function preRender($element) { + // Add button. + $button_img = 'http://s7.addthis.com/static/btn/sm-share-en.gif'; + if ($element['#size'] === 'big') { + $button_img = 'http://s7.addthis.com/static/btn/v2/lg-share-en.gif'; + } + + // Create img button. + $element['image'] = [ + '#theme' => 'image', + '#uri' => $button_img, + '#alt' => t('Share page with AddThis'), + ]; + + + $script_manager = \Drupal::getContainer()->get('addthis.script_manager'); + $script_manager->attachJsToElement($element); + + return $element; + } + +} \ No newline at end of file diff --git a/src/Element/AddThisBasicToolbox.php b/src/Element/AddThisBasicToolbox.php new file mode 100644 index 0000000..6e499a0 --- /dev/null +++ b/src/Element/AddThisBasicToolbox.php @@ -0,0 +1,92 @@ + 'addthis_basic_toolbox', + '#size' => 'addthis_16x16_style', + '#services' => 'facebook,twitter', + '#extra_classes' => '', + '#counter_orientation' => 'horizontal', + '#pre_render' => [ + [$class, 'preRender'], + ], + ]; + } + + + public static function preRender($element) { + // Add Script. + $script_manager = \Drupal::getContainer()->get('addthis.script_manager'); + $script_manager->attachJsToElement($element); + + $services = trim($element['#services']); + $services = str_replace(' ', '', $services); + $services = explode(',', $services); + + // Orientation + if ($element['#counter_orientation'] == 'vertical') { + $isvertical = TRUE; + } + + foreach ($services as $key => $service) { + $element['services'][$key] = array(); + $element['services'][$key]['service'] = $service; + $attributes = [ + 'class' => ['addthis_button_' . $service] + ]; + switch ($service) { + case 'linkedin_counter': + $attributes['li:counter'] = $isvertical ? 'top' : ''; + break; + case 'facebook_like': + $attributes['fb:like:layout'] = $isvertical ? 'box_count' : 'button_count'; + break; + case 'facebook_share': + $attributes['fb:share:layout'] = $isvertical ? 'box_count' : 'button_count'; + break; + case 'google_plusone': + $attributes['g:plusone:size'] = $isvertical ? 'tall' : 'standard'; + break; + case 'tweet': + $attributes['tw:count'] = $isvertical ? 'vertical' : 'horizontal'; + // $attributes['tw:via'] = $isvertical ? 'vertical' : 'horizontal'; // TODO: D7 used AddThis::getInstance()->getTwitterVia() + break; + case 'bubble_style': + $attributes['class'][] = 'addthis_counter'; + $attributes['class'][] = 'addthis_bubble_style'; + break; + case 'pill_style': + $attributes['class'][] = 'addthis_counter'; + $attributes['class'][] = 'addthis_pill_style'; + break; + } + + $element['services'][$key]['attributes'] = new Attribute($attributes); + + } + + + return $element; + } + +} \ No newline at end of file diff --git a/src/Form/AddThisSettingsAdvancedForm.php b/src/Form/AddThisSettingsAdvancedForm.php new file mode 100644 index 0000000..ae8be16 --- /dev/null +++ b/src/Form/AddThisSettingsAdvancedForm.php @@ -0,0 +1,135 @@ + 'details', + '#title' => t('Service URLs'), + '#open' => TRUE, + ); + $form['service_urls_details']['addthis_bookmark_url'] = array( + '#type' => 'textfield', + '#title' => t('AddThis bookmark URL'), + '#default_value' => $config->get('addthis_bookmark_url'), + '#required' => TRUE, + ); + $form['service_urls_details']['addthis_services_css_url'] = array( + '#type' => 'textfield', + '#title' => t('AddThis services stylesheet URL'), + '#default_value' => $config->get('addthis_services_css_url'), + '#required' => TRUE, + ); + $form['service_urls_details']['addthis_services_json_url'] = array( + '#type' => 'textfield', + '#title' => t('AddThis services json URL'), + '#default_value' => $config->get('addthis_services_json_url'), + '#required' => TRUE, + ); + $form['service_urls_details']['addthis_widget_js_url'] = array( + '#type' => 'textfield', + '#title' => t('AddThis javascript widget URL'), + '#default_value' => $config->get('addthis_widget_js_url'), + '#required' => TRUE, + ); + + // Advanced settings. + $form['advanced_settings_details'] = array( + '#type' => 'details', + '#title' => t('Advanced settings'), + '#access' => \Drupal::currentUser() + ->hasPermission('administer advanced addthis'), + '#open' => TRUE, + ); + $form['advanced_settings_details']['addthis_custom_configuration_code_enabled'] = array( + '#type' => 'checkbox', + '#title' => t('Use custom AddThis configuration code'), + '#default_value' => $config->get('addthis_custom_configuration_code_enabled'), + '#required' => FALSE, + '#description' => t('Use custom AddThis configuration code. If checked, custom configuration will be used instead of other configuration settings provided in AddThis administration user interface.'), + ); + $form['advanced_settings_details']['addthis_custom_configuration_code'] = array( + '#type' => 'textarea', + '#title' => t('AddThis custom configuration code'), + '#default_value' => $config->get('addthis_custom_configuration_code'), + '#required' => FALSE, + '#description' => t('AddThis custom configuration code. See format at AddThis.com'), + ); + $form['advanced_settings_details']['addthis_widget_load_async'] = array( + '#type' => 'checkbox', + '#title' => t('Initialize asynchronously through addthis.init().'), + '#description' => t('Use this when you have your own Ajax functionality or create things after the DOM is ready trough Javascript. Initialize the addthis functionality through addthis.init().'), + '#default_value' => $config->get('addthis_widget_load_async'), + ); + $form['advanced_settings_details']['addthis_widget_include'] = array( + '#type' => 'select', + '#title' => t('Load widget js.'), + '#options' => array( + '0' => t('Don\'t include at all.'), + '1' => t('Include on all (non admin) pages'), + '2' => t('(Default) Include on widget rendering by Drupal.'), + ), + '#default_value' => $config->get('addthis_widget_include'), + ); + + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $this->config('addthis.settings.advanced') + ->set('addthis_bookmark_url', $form_state->getValue('addthis_bookmark_url')) + ->set('addthis_services_css_url_key', $form_state->getValue('addthis_services_css_url_key')) + ->set('addthis_services_json_url_key', $form_state->getValue('addthis_services_json_url_key')) + ->set('addthis_widget_js_url', $form_state->getValue('addthis_widget_js_url')) + ->set('addthis_custom_configuration_code_enabled', $form_state->getValue('addthis_custom_configuration_code_enabled')) + ->set('addthis_custom_configuration_code', $form_state->getValue('addthis_custom_configuration_code')) + ->set('addthis_widget_load_async', $form_state->getValue('addthis_widget_load_async')) + ->set('addthis_widget_include', $form_state->getValue('addthis_widget_include')) + ->save(); + + parent::submitForm($form, $form_state); + } + +} + diff --git a/src/Form/AddThisSettingsForm.php b/src/Form/AddThisSettingsForm.php index 43c22cb..24bf17e 100644 --- a/src/Form/AddThisSettingsForm.php +++ b/src/Form/AddThisSettingsForm.php @@ -6,11 +6,11 @@ namespace Drupal\addthis\Form; +use Drupal\addthis\AddThisScriptManager; +use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Extension\ModuleHandler; use Drupal\Component\Utility\Xss; -use Drupal\addthis\AddThis; /** * Defines a form to configure maintenance settings for this site. @@ -36,22 +36,26 @@ protected function getEditableConfigNames() { */ public function buildForm(array $form, FormStateInterface $form_state) { $config = $this->config('addthis.settings'); + $add_this_script_manager = \Drupal::service('addthis.script_manager'); + + + //Add our library to the settings form to add in custom CSS. + $form['#attached']['library'][] = 'addthis/addthis.admin'; // Visual settings. - $form['fieldset_compact_menu'] = array( - '#type' => 'fieldset', + $form['compact_menu'] = array( + '#type' => 'details', '#title' => t('Compact menu'), - '#collapsible' => FALSE, - '#collapsed' => TRUE, - '#description' => '

' . t('Configure the global behavior and style of the compact menu and some additional settings related to the interface.') . '

' + '#open' => TRUE, + '#description' => '

' . t('Configure the global behavior and style of the compact menu and some additional settings related to the interface.') . '

', + '#description_display' => 'before' ); - $form['fieldset_compact_menu']['fieldset_menu_style'] = array( - '#type' => 'fieldset', + $form['compact_menu']['menu_style'] = array( + '#type' => 'details', '#title' => t('Style'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, + '#open' => FALSE, ); - $form['fieldset_compact_menu']['fieldset_menu_style']['addthis_co_brand'] = array( + $form['compact_menu']['menu_style']['addthis_co_brand'] = array( '#type' => 'textfield', '#title' => t('Branding text'), '#description' => t('Additional branding message to be rendered in the upper-right-hand corner of the compact menus.
Should be less than 15 characters in most cases to render properly.'), @@ -59,39 +63,39 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#required' => FALSE, '#maxlength' => 15, ); - $form['fieldset_compact_menu']['fieldset_menu_style']['addthis_ui_header_color'] = array( + $form['compact_menu']['menu_style']['addthis_ui_header_color'] = array( '#type' => 'textfield', '#title' => t('Header text color'), '#default_value' => $config->get('compact_menu.menu_style.addthis_ui_header_color'), - '#description' => t('Something like #FFFFFF'), + '#description' => t('Something like \'#FFFFFF\'.'), '#size' => 8, '#maxlength' => 7, '#required' => FALSE, ); - $form['fieldset_compact_menu']['fieldset_menu_style']['addthis_ui_header_background_color'] = array( + $form['compact_menu']['menu_style']['addthis_ui_header_background_color'] = array( '#type' => 'textfield', '#title' => t('Header background color'), '#default_value' => $config->get('compact_menu.menu_style.addthis_ui_header_background_color'), - '#description' => t('Something like #000000'), + '#description' => t('Something like \'#000000\'.'), '#size' => 8, '#maxlength' => 7, '#required' => FALSE, ); - $form['fieldset_compact_menu']['fieldset_menu_style']['addthis_click_to_open_compact_menu_enabled'] = array( + $form['compact_menu']['menu_style']['addthis_click_to_open_compact_menu_enabled'] = array( '#type' => 'checkbox', '#title' => t('Open compact menu on click'), '#description' => t('Default behavior is to open compact menu on hover.'), '#default_value' => $config->get('compact_menu.menu_style.addthis_click_to_open_compact_menu_enabled'), '#required' => FALSE, ); - $form['fieldset_compact_menu']['fieldset_menu_style']['addthis_open_windows_enabled'] = array( + $form['compact_menu']['menu_style']['addthis_open_windows_enabled'] = array( '#type' => 'checkbox', '#title' => t('Use pop-up windows'), '#description' => t('If checked, all shares will open in a new pop-up window instead of a new tab or regular browser window.'), '#default_value' => $config->get('compact_menu.menu_style.addthis_open_windows_enabled'), '#required' => FALSE, ); - $form['fieldset_compact_menu']['fieldset_menu_style']['addthis_ui_delay'] = array( + $form['compact_menu']['menu_style']['addthis_ui_delay'] = array( '#type' => 'textfield', '#title' => t('Menu open delay'), '#description' => t('Delay, in milliseconds, before compact menu appears when mousing over a regular button. Capped at 500 ms.'), @@ -102,44 +106,44 @@ public function buildForm(array $form, FormStateInterface $form_state) { ); // Enabled services settings. - $form['fieldset_compact_menu']['enabled_services_fieldset'] = array( - '#type' => 'fieldset', + $form['compact_menu']['enabled_services'] = array( + '#type' => 'details', '#title' => t('Compact menu enabled services'), '#description' => t('The sharing services you select here will be displayed in the compact menu. If you select no services, AddThis will provide a list of frequently used services. This list is updated regularly. Notice that this setting does not define what services should be display in a toolbox.'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, + '#description_display' => 'before', + '#open' => FALSE, ); - $form['fieldset_compact_menu']['enabled_services_fieldset']['addthis_enabled_services'] = array( + + $form['compact_menu']['enabled_services']['addthis_enabled_services'] = array( '#type' => 'checkboxes', '#title' => t('Enabled services'), - '#options' => AddThis::getInstance()->getServices(), + '#options' => $add_this_script_manager->getServices(), '#default_value' => $config->get('compact_menu.enabled_services.addthis_enabled_services'), '#required' => FALSE, '#columns' => 3, ); // Additional visual settings. - $form['fieldset_compact_menu']['fieldset_additionals'] = array( - '#type' => 'fieldset', + $form['compact_menu']['additionals'] = array( + '#type' => 'details', '#title' => t('Additional configuration'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, + '#open' => FALSE, ); - $form['fieldset_compact_menu']['fieldset_additionals']['addthis_standard_css_enabled'] = array( + $form['compact_menu']['additionals']['addthis_standard_css_enabled'] = array( '#type' => 'checkbox', '#title' => t('Use standard AddThis stylesheet'), '#description' => t('If not checked, AddThis will not load standard CSS file, allowing you to style everything yourself without incurring the cost of an additional load.'), '#default_value' => $config->get('compact_menu.additionals.addthis_standard_css_enabled'), '#required' => FALSE, ); - $form['fieldset_compact_menu']['fieldset_additionals']['addthis_508_compliant'] = array( + $form['compact_menu']['additionals']['addthis_508_compliant'] = array( '#type' => 'checkbox', '#title' => t('508 compliant'), '#description' => 'If checked, clicking the AddThis button will open a new window to a page that is keyboard navigable.', '#default_value' => $config->get('compact_menu.additionals.addthis_508_compliant'), '#required' => FALSE, ); - $form['fieldset_compact_menu']['fieldset_additionals']['addthis_addressbook_enabled'] = array( + $form['compact_menu']['additionals']['addthis_addressbook_enabled'] = array( '#type' => 'checkbox', '#title' => t('Use addressbook'), '#description' => 'If checked, the user will be able import their contacts from popular webmail services when using AddThis\'s email sharing.', @@ -148,41 +152,41 @@ public function buildForm(array $form, FormStateInterface $form_state) { ); // Excluded Services. - $form['fieldset_excluded_services'] = array( - '#type' => 'fieldset', + $form['excluded_services'] = array( + '#type' => 'details', '#title' => t('Excluded services'), '#description' => t('The sharing services you select here will be excluded from all AddThis menus. This applies globally.'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, + '#description_display' => 'before', + '#open' => FALSE, ); - $form['fieldset_excluded_services']['addthis_excluded_services'] = array( + $form['excluded_services']['addthis_excluded_services'] = array( '#type' => 'checkboxes', '#title' => t('Excluded services'), - '#options' => AddThis::getInstance()->getServices(), + '#options' => $add_this_script_manager->getServices(), '#default_value' => $config->get('excluded_services.addthis_excluded_services'), '#required' => FALSE, '#columns' => 3, ); - //Analytics settings. + //Analytics settings. $profile_id = $config->get('analytics.addthis_profile_id'); $can_track_clicks = empty($profile_id) ? FALSE : TRUE; - $form['fieldset_analytics'] = array( - '#type' => 'fieldset', - '#title' => t('Analytics & Tracking'), - '#collapsible' => TRUE, - '#collapsed' => $can_track_clicks ? TRUE : FALSE, + $form['analytics'] = array( + '#type' => 'details', + '#title' => t('Analytics and Tracking'), + '#open' => $can_track_clicks ? TRUE : FALSE, ); if (!$can_track_clicks) { - $form['fieldset_analytics']['can_track_notice'] = array( + $form['analytics']['can_track_notice'] = array( '#theme' => 'html_tag', '#tag' => 'div', '#value' => t('For click analytics and statistics you have to provide a ProfileID from AddThis.com. Register here.'), '#attributes' => array('class' => array('messages', 'warning')), ); } - $form['fieldset_analytics']['addthis_profile_id'] = array( + + $form['analytics']['addthis_profile_id'] = array( '#type' => 'textfield', '#title' => t('AddThis ProfileID'), '#default_value' => $config->get('analytics.addthis_profile_id'), @@ -190,7 +194,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#size' => 25, '#description' => t('ProfileID at AddThis.com. Required for statistics.'), ); - $form['fieldset_analytics']['addthis_clickback_tracking_enabled'] = array( + $form['analytics']['addthis_clickback_tracking_enabled'] = array( '#type' => 'checkbox', '#title' => t('Track clickback'), '#description' => 'Check to allow AddThis to append a variable to your URLs upon sharing. AddThis will use this to track how many people come back to your content via links shared with AddThis. Highly recommended. Always global.', @@ -208,19 +212,19 @@ public function buildForm(array $form, FormStateInterface $form_state) { else { $rdf_description = t('Check to enable Facebook Like tracking support. Always global.'); } - $form['fieldset_analytics']['title_facebook'] = array( + $form['analytics']['title_facebook'] = array( '#theme' => 'html_tag', '#tag' => 'div', '#value' => '' . t('Facebook') . '', ); - $form['fieldset_analytics']['facebook_notice'] = array( + $form['analytics']['facebook_notice'] = array( '#theme' => 'html_tag', '#tag' => 'p', '#value' => $rdf_description, '#access' => !$rdf_enabled, ); - $form['fieldset_analytics']['addthis_facebook_like_count_support_enabled'] = array( + $form['analytics']['addthis_facebook_like_count_support_enabled'] = array( '#type' => 'checkbox', '#title' => t('Enable Facebook Like tracking'), '#description' => Xss::filter($rdf_description, array('span')), @@ -230,31 +234,35 @@ public function buildForm(array $form, FormStateInterface $form_state) { ); // Google Analytics and Google Social Tracking support. - $can_do_google_social_tracking = \Drupal::moduleHandler()->moduleExists('googleanalytics'); + $can_do_google_social_tracking = \Drupal::moduleHandler() + ->moduleExists('google_analytics'); //@TODO Get back to this. - $google_analytics_config = \Drupal::config(google_analytics.settings); + $google_analytics_config = $this->configFactory()->get('google_analytics.settings'); $google_analytics_account = $google_analytics_config->get('google_analytics_account'); $is_google_analytics_setup = $can_do_google_social_tracking && isset($google_analytics_account); - $form['fieldset_analytics']['google_analytics'] = array( - '#theme' => 'html_tag', - '#tag' => 'div', - '#value' => '' . t('Google Analytics') . '', + $form['analytics']['google_analytics'] = array( + '#type' => 'markup', + '#prefix' => '
', + '#suffix' => '
', + '#markup' => '' . t('Google Analytics') . '', ); if (!$can_do_google_social_tracking) { - $form['fieldset_analytics']['can_do_google_analytics'] = array( - '#theme' => 'html_tag', - '#tag' => 'p', - '#value' => '' . t('Install/enable the Google Analytics module for Social Tracking support.') . '', + $form['analytics']['can_do_google_analytics'] = array( + '#type' => 'markup', + '#prefix' => '

', + '#suffix' => '

', + '#markup' => '' . t('Install/enable the Google Analytics module for Social Tracking support.') . '', ); } elseif ($can_do_google_social_tracking && !$is_google_analytics_setup) { - $form['fieldset_analytics']['can_do_google_analytics'] = array( - '#theme' => 'html_tag', - '#tag' => 'p', + $form['analytics']['can_do_google_analytics'] = array( + '#type' => 'markup', + '#prefix' => '

', + '#suffix' => '

', '#value' => '' . t('Configure the Google Analytics module correctly with the account code to use this feature.') . '', ); } - $form['fieldset_analytics']['addthis_google_analytics_tracking_enabled'] = array( + $form['analytics']['addthis_google_analytics_tracking_enabled'] = array( '#type' => 'checkbox', '#title' => t('Track with Google Analytics'), '#description' => t('Check to track shares in your Google Analytics account reports (more info). Always global.'), @@ -262,7 +270,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#required' => FALSE, '#disabled' => !$is_google_analytics_setup, ); - $form['fieldset_analytics']['addthis_google_analytics_social_tracking_enabled'] = array( + $form['analytics']['addthis_google_analytics_social_tracking_enabled'] = array( '#type' => 'checkbox', '#title' => t('Track with Google Analytics social'), '#description' => t('Check to track shares in the new Google Analytics social interaction reports (more info). Always global.'), @@ -272,26 +280,25 @@ public function buildForm(array $form, FormStateInterface $form_state) { ); // Third party settings. - $form['third_party_fieldset'] = array( - '#type' => 'fieldset', + $form['third_party'] = array( + '#type' => 'details', '#title' => t('Third party settings'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, + '#open' => FALSE, ); - $form['third_party_fieldset']['twitter_service'] = array( + $form['third_party']['twitter_service'] = array( '#type' => 'fieldset', '#title' => t('Twitter'), '#collapsible' => TRUE, '#collapsed' => TRUE, ); - $form['third_party_fieldset']['twitter_service']['addthis_twitter_via'] = array( + $form['third_party']['twitter_service']['addthis_twitter_via'] = array( '#type' => 'textfield', '#title' => t('Send via'), '#description' => t('When sending a tweet this is the screen name of the user to attribute the Tweet to. (Relates to Tweet Button)'), '#default_value' => $config->get('third_party.addthis_twitter_via'), '#size' => 15, ); - $form['third_party_fieldset']['twitter_service']['addthis_twitter_template'] = array( + $form['third_party']['twitter_service']['addthis_twitter_template'] = array( '#type' => 'textfield', '#title' => t('Template text'), '#description' => t('The {{title}} and {{url}} are replaced from the Twitter Button.'), diff --git a/src/Plugin/Block/AddThisBlock.php b/src/Plugin/Block/AddThisBlock.php index b752933..332e023 100644 --- a/src/Plugin/Block/AddThisBlock.php +++ b/src/Plugin/Block/AddThisBlock.php @@ -6,9 +6,10 @@ namespace Drupal\addthis\Plugin\Block; +use Drupal\addthis\AddThisBasicButtonFormTrait; +use Drupal\addthis\AddThisBasicToolboxFormTrait; use Drupal\Core\Block\BlockBase; use Drupal\Core\Form\FormStateInterface; -use Drupal\addthis\AddThis; /** * Provides my custom block. @@ -19,29 +20,154 @@ * category = @Translation("Blocks") * ) */ -class AddThisBlock extends BlockBase -{ +class AddThisBlock extends BlockBase { + + use AddThisBasicButtonFormTrait; + use AddThisBasicToolboxFormTrait; /** * {@inheritdoc} */ - public function build() - { - //@TODO Implement block markup - $markup = 'Testing Markup'; + public function defaultConfiguration() { return array( - '#markup' => $markup, + 'display_type' => 'addthis_basic_button', + 'basic_toolbox' => $this->addThisBasicToolboxGetDefaults(), + 'basic_button' => $this->addThisBasicButtonGetDefaults(), ); } + /** + * {@inheritdoc} + */ function blockForm($form, FormStateInterface $form_state) { - //@TODO: Implement block form. + $settings = $this->getConfiguration(); + + //get type from config + $default_type = $settings['display_type']; + + $selected_type = $form_state->getValue([ + 'settings', + 'addthis_settings', + 'display_type' + ]); + + $selected_type = isset($selected_type) ? $selected_type : $default_type; + + + $form['addthis_settings'] = array( + '#type' => 'fieldset', + '#title' => 'Display settings', + + ); + + $form['addthis_settings']['display_type'] = array( + '#type' => 'select', + '#title' => t('Formatter for @title', array('@title' => 'AddThis block')), + '#title_display' => 'invisible', + '#options' => [ + 'addthis_basic_button' => 'AddThis Basic Button', + 'addthis_basic_toolbox' => 'AddThis Basic Toolbox', + ], + '#default_value' => isset($default_type) ? $default_type : 'addthis_basic_button', + '#attributes' => array('class' => array('addthis-display-type')), + '#ajax' => array( + 'callback' => array($this, 'addthisAjaxCallback'), + 'wrapper' => 'addthis_type_settings', + ), + ); + $form['addthis_settings']['type_settings'] = array( + '#prefix' => '
'
', + ); + if (isset($selected_type) && $selected_type == 'addthis_basic_toolbox') { + $basicToolbox = $this->addThisBasicToolboxForm($settings['basic_toolbox']); + $form['addthis_settings']['type_settings']['basic_toolbox'] = $basicToolbox; + } + else { + if (isset($selected_type) && $selected_type == 'addthis_basic_button') { + $basicButton = $this->addThisBasicButtonForm($settings['basic_button']); + $form['addthis_settings']['type_settings']['basic_button'] = $basicButton; + } + } + + return $form; } + + /** + * Callback for AddThisBlock blockForm() to control sub-settings based on display type. + * @param array $form + * @param FormStateInterface $form_state + * @return mixed + */ + public function addthisAjaxCallback(array $form, FormStateInterface $form_state) { + return $form['settings']['addthis_settings']['type_settings']; + } + + /** + * {@inheritdoc} + */ public function blockSubmit($form, FormStateInterface $form_state) { - //@TODO: Implement block submit. + + //@TODO Settings for unselected type get wiped because they dont exist in form. + // Try not to overwrite them if possible. + $this->configuration['display_type'] = $form_state->getValue([ + 'addthis_settings', + 'display_type' + ]); + + //Handle saving the partial elements provided by AddThisBasicToolboxFormTrait. + $basicToolboxKeys = $this->addThisBasicToolboxGetDefaults(); + foreach ($basicToolboxKeys as $key => $value) { + $this->configuration['basic_toolbox'][$key] = $form_state->getValue([ + 'addthis_settings', + 'type_settings', + 'basic_toolbox', + $key + ]); + } + + //Handle saving the partial elements provided by AddThisBasicButtonFormTrait. + $basicButtonKeys = $this->addThisBasicButtonGetDefaults(); + foreach ($basicButtonKeys as $key => $value) { + $this->configuration['basic_button'][$key] = $form_state->getValue([ + 'addthis_settings', + 'type_settings', + 'basic_button', + $key + ]); + } + + } -} + /** + * {@inheritdoc} + */ + public function build() { + $config = $this->configuration; + + switch ($config['display_type']) { + case 'addthis_basic_button': + return [ + '#type' => 'addthis_basic_button', + '#size' => $config['basic_button']['button_size'], + '#extra_classes' => $config['basic_button']['extra_css'], + ]; + break; + case 'addthis_basic_toolbox': + return [ + '#type' => 'addthis_basic_toolbox', + '#size' => $config['basic_toolbox']['buttons_size'], + '#services' => $config['basic_toolbox']['share_services'], + '#extra_classes' => $config['basic_toolbox']['extra_css'], + '#counter_orientation' => $config['basic_toolbox']['counter_orientation'], + ]; + break; + } -?> \ No newline at end of file + return [ + '#markup' => '' + ]; + } +} diff --git a/src/Plugin/Field/FieldFormatter/AddThisBasicButtonFormatter.php b/src/Plugin/Field/FieldFormatter/AddThisBasicButtonFormatter.php new file mode 100644 index 0000000..d7b741c --- /dev/null +++ b/src/Plugin/Field/FieldFormatter/AddThisBasicButtonFormatter.php @@ -0,0 +1,61 @@ + 'small', + 'extra_css' => '', + ) + parent::defaultSettings(); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $settings = $this->getSettings(); + $element = $this->addThisBasicButtonForm($settings); + + return $element; + } + + + /** + * {@inheritdoc} + */ + public function viewElements(FieldItemListInterface $items) { + $settings = $this->getSettings(); + return array( + '#type' => 'addthis_basic_button', + '#size' => $settings['button_size'], + '#extra_classes' => $settings['extra_css'], + ); + } +} \ No newline at end of file diff --git a/src/Plugin/Field/FieldFormatter/AddThisBasicToolboxFormatter.php b/src/Plugin/Field/FieldFormatter/AddThisBasicToolboxFormatter.php new file mode 100644 index 0000000..153c84a --- /dev/null +++ b/src/Plugin/Field/FieldFormatter/AddThisBasicToolboxFormatter.php @@ -0,0 +1,64 @@ + 'facebook,twitter', + 'buttons_size' => 'addthis_16x16_style', + 'counter_orientation' => 'horizontal', + 'extra_css' => '', + ) + parent::defaultSettings(); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $settings = $this->getSettings(); + $element = $this->addThisBasicToolboxForm($settings); + + return $element; + } + + + /** + * {@inheritdoc} + */ + public function viewElements(FieldItemListInterface $items) { + $settings = $this->getSettings(); + return array( + '#type' => 'addthis_basic_toolbox', + '#size' => $settings['buttons_size'], + '#services' => $settings['share_services'], + '#extra_classes' => $settings['extra_css'], + ); + } + +} \ No newline at end of file diff --git a/src/Plugin/Field/FieldFormatter/AddThisFormatter.php b/src/Plugin/Field/FieldFormatter/AddThisFormatter.php index 0052c4c..08e32ef 100644 --- a/src/Plugin/Field/FieldFormatter/AddThisFormatter.php +++ b/src/Plugin/Field/FieldFormatter/AddThisFormatter.php @@ -1,8 +1,8 @@ array(), + ); } } \ No newline at end of file diff --git a/src/Plugin/Field/FieldType/AddThisItem.php b/src/Plugin/Field/FieldType/AddThisItem.php index 536df80..cc66b76 100644 --- a/src/Plugin/Field/FieldType/AddThisItem.php +++ b/src/Plugin/Field/FieldType/AddThisItem.php @@ -31,10 +31,7 @@ class AddThisItem extends FieldItemBase { * {@inheritdoc} */ public static function defaultStorageSettings() { - return array( - 'max_length' => 255, - 'is_ascii' => FALSE, - ) + parent::defaultStorageSettings(); + return [] + parent::defaultStorageSettings(); } /** @@ -44,9 +41,8 @@ public static function schema(FieldStorageDefinitionInterface $field_definition) return array( 'columns' => array( 'value' => array( - 'type' => $field_definition->getSetting('is_ascii') === TRUE ? 'varchar_ascii' : 'varchar', - 'length' => (int) $field_definition->getSetting('max_length'), - 'binary' => $field_definition->getSetting('case_sensitive'), + 'type' => 'varchar', + 'length' => 255, ), ), ); @@ -59,27 +55,6 @@ public function isEmpty() { return FALSE; } - /** - * {@inheritdoc} - */ - public function getConstraints() { - $constraints = parent::getConstraints(); - - if ($max_length = $this->getSetting('max_length')) { - $constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager(); - $constraints[] = $constraint_manager->create('ComplexData', array( - 'value' => array( - 'Length' => array( - 'max' => $max_length, - 'maxMessage' => t('%name: may not be longer than @max characters.', array('%name' => $this->getFieldDefinition()->getLabel(), '@max' => $max_length)), - ), - ), - )); - } - - return $constraints; - } - /** * {@inheritdoc} @@ -88,10 +63,7 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel // This is called very early by the user entity roles field. Prevent // early t() calls by using the TranslationWrapper. $properties['value'] = DataDefinition::create('string') - ->setLabel(new TranslationWrapper('Text value')) - ->setSetting('case_sensitive', $field_definition->getSetting('case_sensitive')) - ->setRequired(TRUE); - + ->setLabel(new TranslationWrapper('Text value')); return $properties; } diff --git a/src/Plugin/Field/FieldWidget/AddThisWidget.php b/src/Plugin/Field/FieldWidget/AddThisWidget.php index 2f4c6f7..ada3a4f 100644 --- a/src/Plugin/Field/FieldWidget/AddThisWidget.php +++ b/src/Plugin/Field/FieldWidget/AddThisWidget.php @@ -18,7 +18,7 @@ * id = "addthis_button_widget", * label = @Translation("AddThis button"), * field_types = { - * "disabled" + * "addthis" * }, * multiple_values = FALSE * ) @@ -29,8 +29,7 @@ class AddThisWidget extends WidgetBase { * {@inheritdoc} */ public static function defaultSettings() { - return array( - ) + parent::defaultSettings(); + return array() + parent::defaultSettings(); } /** diff --git a/src/Tests/AddThisBaseTest.php b/src/Tests/AddThisBaseTest.php new file mode 100644 index 0000000..8dc187a --- /dev/null +++ b/src/Tests/AddThisBaseTest.php @@ -0,0 +1,71 @@ +adminUser = $this->drupalCreateUser([ + 'administer blocks', + ]); + $this->drupalLogin($this->adminUser); + } + /** + * Tests ability to add a block to the page. + * - Adds AddThis block to content region + * - Verifies the block displays + */ + public function testAddThisAddBlockToPage(){ + + $block = $this->drupalPlaceBlock('addthis', [ + 'label' => 'AddThis Block', + 'region' => 'content', + ]); + + $this->drupalGet(''); + $this->assertBlockAppears($block); + } + + /** + * Tests ability to create a block with "addthis_basic_toolbox" and verifies the form fields. + * - Creates an AddThis block + * - Sets Display type to addthis_basic_toolbox + * - Confirms fields are available + * - Saves block settings + * - Confirms configuration was saved successfully. + * + * @throws \Exception + */ + public function testAddThisBlockToolboxConfig(){ + $block = array(); + $block['id'] = 'addthis_block'; + $block['settings[label]'] = $this->randomMachineName(8); + $block['theme'] = $this->config('system.theme')->get('default'); + $block['region'] = 'content'; + $edit = array( + 'settings[label]' => $block['settings[label]'], + 'id' => $block['id'], + 'region' => $block['region'], + 'settings[addthis_settings][display_type]' => 'addthis_basic_toolbox', + ); + + //Create Block with type=addthis_basic_toolbox + $this->drupalPostForm('admin/structure/block/add/' . $block['id'] . '/' . $block['theme'], $edit, t('Save block')); + $this->assertText(t('The block configuration has been saved.'), 'AddThis block has been created.'); + + //Load up new block. + $this->drupalGet('admin/structure/block/manage/' . $block['id']); + //Verify form fields for toolbox are here. + $this->assertFieldByName('settings[addthis_settings][type_settings][basic_toolbox][share_services]'); + $this->assertFieldByName('settings[addthis_settings][type_settings][basic_toolbox][buttons_size]'); + $this->assertFieldByName('settings[addthis_settings][type_settings][basic_toolbox][counter_orientation]'); + $this->assertFieldByName('settings[addthis_settings][type_settings][basic_toolbox][extra_css]'); + + //Test saving and loading config works. + $edit = [ + 'settings[addthis_settings][display_type]' => 'addthis_basic_toolbox', + 'settings[addthis_settings][type_settings][basic_toolbox][share_services]' => 'twitter,facebook,compact', + 'settings[addthis_settings][type_settings][basic_toolbox][buttons_size]' => 'addthis_32x32_style', + 'settings[addthis_settings][type_settings][basic_toolbox][counter_orientation]' => 'vertical', + 'settings[addthis_settings][type_settings][basic_toolbox][extra_css]' => $this->randomMachineName(), + ]; + $this->drupalPostForm('admin/structure/block/manage/' . $block['id'], $edit, t('Save block')); + $this->drupalGet('admin/structure/block/manage/' . $block['id']); + $this->assertRaw($edit['settings[addthis_settings][display_type]'], 'Content of configurable type successfully verified.'); + $this->assertRaw($edit['settings[addthis_settings][type_settings][basic_toolbox][share_services]'], 'Content of configurable share services block successfully verified.'); + $this->assertRaw($edit['settings[addthis_settings][type_settings][basic_toolbox][buttons_size]'], 'Content of configurable button size block successfully verified.'); + $this->assertRaw($edit['settings[addthis_settings][type_settings][basic_toolbox][counter_orientation]'], 'Content of configurable counter orientation block successfully verified.'); + $this->assertRaw($edit['settings[addthis_settings][type_settings][basic_toolbox][extra_css]'], 'Content of configurable extra css block successfully verified.'); + + + + } + + /** + * Tests the validation for the AddThisBasicToolbox service settings. + * - Creates AddThis block + * - Sets Display type to addthis_basic_toolbox + * - Tests for failed validation for services field + * - Tests for successful validation for services field + * + * @throws \Exception + */ + public function testAddThisBlockToolboxServicesValidation(){ + $block = array(); + $block['id'] = 'addthis_block'; + $block['settings[label]'] = $this->randomMachineName(8); + $block['theme'] = $this->config('system.theme')->get('default'); + $block['region'] = 'content'; + $edit = array( + 'settings[label]' => $block['settings[label]'], + 'id' => $block['id'], + 'region' => $block['region'], + 'settings[addthis_settings][display_type]' => 'addthis_basic_toolbox', + ); + + $this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default')); + + $this->drupalPostForm('admin/structure/block/add/' . $block['id'] . '/' . $block['theme'], $edit, t('Save block')); + $this->assertText(t('The block configuration has been saved.'), 'AddThis block has been created.'); + + //Test - validation should fail. + $edit = [ + 'settings[addthis_settings][display_type]' => 'addthis_basic_toolbox', + 'settings[addthis_settings][type_settings][basic_toolbox][share_services]' => '', + ]; + $this->drupalPostForm('admin/structure/block/manage/' . $block['id'], $edit, t('Save block')); + $this->assertText(t('Services field is required.'), 'AddThis block validation failed because services was empty.'); + + //Test - validation should fail. + $edit = [ + 'settings[addthis_settings][display_type]' => 'addthis_basic_toolbox', + 'settings[addthis_settings][type_settings][basic_toolbox][share_services]' => 'facebook,twitter,!@#@!$%!@$@!$', + ]; + $this->drupalPostForm('admin/structure/block/manage/' . $block['id'], $edit, t('Save block')); + $this->assertText(t('The declared services are incorrect or nonexistent.'), 'AddThis block validation failed because services has special characters.'); + + + //Test - validation should pass. + $edit = [ + 'settings[addthis_settings][display_type]' => 'addthis_basic_toolbox', + 'settings[addthis_settings][type_settings][basic_toolbox][share_services]' => 'twitter,facebook,compact', + ]; + $this->drupalPostForm('admin/structure/block/manage/' . $block['id'], $edit, t('Save block')); + $this->assertText(t('The block configuration has been saved.'), 'AddThis block saved.'); + + + } + + + /** + * Tests ability to create a block with "addthis_basic_button" and verifies the form fields. + * - Creates an AddThis block + * - Sets Display type to addthis_basic_button + * - Confirms fields are available + * - Saves block settings + * - Confirms configuration was saved successfully. + * @throws \Exception + */ + public function testAddThisBlockButtonConfig(){ + $block = array(); + $block['id'] = 'addthis_block'; + $block['settings[label]'] = $this->randomMachineName(8); + $block['theme'] = $this->config('system.theme')->get('default'); + $block['region'] = 'content'; + $edit = array( + 'settings[label]' => $block['settings[label]'], + 'id' => $block['id'], + 'region' => $block['region'], + 'settings[addthis_settings][display_type]' => 'addthis_basic_button', + ); + + //Create Block with type=addthis_basic_toolbox + $this->drupalPostForm('admin/structure/block/add/' . $block['id'] . '/' . $block['theme'], $edit, t('Save block')); + $this->assertText(t('The block configuration has been saved.'), 'AddThis block has been created.'); + + //Load up new block. + $this->drupalGet('admin/structure/block/manage/' . $block['id']); + //Verify form fields for toolbox are here. + $this->assertFieldByName('settings[addthis_settings][type_settings][basic_button][button_size]'); + $this->assertFieldByName('settings[addthis_settings][type_settings][basic_button][extra_css]'); + + //Verify block config saves and loads properly + $edit = array( + 'settings[addthis_settings][display_type]' => 'addthis_basic_button', + 'settings[addthis_settings][type_settings][basic_button][button_size]' => 'big', + 'settings[addthis_settings][type_settings][basic_button][extra_css]' => $this->randomMachineName(), + ); + $this->drupalPostForm('admin/structure/block/manage/' . $block['id'], $edit, t('Save block')); + //Load up the new block configs. + $this->drupalGet('admin/structure/block/manage/' . $block['id']); + $this->assertRaw($edit['settings[addthis_settings][display_type]'], 'Content of configurable type successfully verified.'); + $this->assertRaw($edit['settings[addthis_settings][type_settings][basic_button][button_size]'], 'Content of configurable button size block successfully verified.'); + $this->assertRaw($edit['settings[addthis_settings][type_settings][basic_button][extra_css]'], 'Content of configurable extra css block successfully verified.'); + + + } + + + +} \ No newline at end of file diff --git a/src/Tests/AddThisFieldTest.php b/src/Tests/AddThisFieldTest.php new file mode 100644 index 0000000..7bafe2d --- /dev/null +++ b/src/Tests/AddThisFieldTest.php @@ -0,0 +1,107 @@ +drupalLogin($this->administratorAccount); + $this->fieldName = $this->createField('addthis', 'addthis_button_widget', '1'); + } + + /** + * Tests the Manage Form settings for the AddThis Toolbox + * - Creates content type + * - Adds AddThis field + * - Visits Manage Form Page + * - Sets display type to "AddThis Basic Toolbox" + * - Verifies form fields. + * - @TODO Confirm saving settings & confrim + */ + public function testAddThisFieldToolboxWidgetForm(){ + // Add a single field as administrator user. + $this->drupalLogin($this->administratorAccount); + $this->fieldName = $this->createField('addthis', 'addthis_button_widget', '1'); + $this->drupalGet('admin/structure/types/manage/'. $this->contentTypeName . '/display'); + $this->assertText($this->fieldName, 'Field is configurable'); + + //Fieldname is set to the name, without field_ so we need to add it back. + $field_key = 'field_' . $this->fieldName; + + //Set the display type to AddThis Toolbox. + $format = 'addthis_basic_toolbox'; + $edit = array( + 'fields[' . $field_key. '][type]' => $format, + 'refresh_rows' => $field_key + ); + $this->drupalPostAjaxForm(NULL, $edit, array('op' => t('Refresh'))); + $this->assertFieldByName('fields[' . $field_key. '][type]', $format, 'The expected formatter is selected.'); + + // Click on the formatter settings button to open the formatter settings + // form. + $this->drupalPostAjaxForm(NULL, array(), $field_key . '_settings_edit'); + + $this->assertFieldByName('fields[' . $field_key . '][settings_edit_form][settings][share_services]'); + $this->assertFieldByName('fields[' . $field_key . '][settings_edit_form][settings][buttons_size]'); + $this->assertFieldByName('fields[' . $field_key . '][settings_edit_form][settings][counter_orientation]'); + $this->assertFieldByName('fields[' . $field_key . '][settings_edit_form][settings][extra_css]'); + + } + + /** + * Tests the Manage Form settings for the AddThis Button + * - Creates content type + * - Adds AddThis field + * - Visits Manage Form Page + * - Sets display type to "AddThis Basic Button" + * - Verifies form fields. + * - @TODO Confirm saving settings & confrim + */ + public function testAddThisFieldButtonWidgetForm(){ + // Add a single field as administrator user. + $this->drupalLogin($this->administratorAccount); + $this->fieldName = $this->createField('addthis', 'addthis_button_widget', '1'); + $this->drupalGet('admin/structure/types/manage/'. $this->contentTypeName . '/display'); + $this->assertText($this->fieldName, 'Field is configurable'); + + //Fieldname is set to the name, without field_ so we need to add it back. + $field_key = 'field_' . $this->fieldName; + + //Set the display type to AddThis Toolbox. + $format = 'addthis_basic_button'; + $edit = array( + 'fields[' . $field_key. '][type]' => $format, + 'refresh_rows' => $field_key + ); + $this->drupalPostAjaxForm(NULL, $edit, array('op' => t('Refresh'))); + $this->assertFieldByName('fields[' . $field_key. '][type]', $format, 'The expected formatter is selected.'); + + // Click on the formatter settings button to open the formatter settings + // form. + $this->drupalPostAjaxForm(NULL, array(), $field_key . '_settings_edit'); + + $this->assertFieldByName('fields[' . $field_key . '][settings_edit_form][settings][button_size]'); + $this->assertFieldByName('fields[' . $field_key . '][settings_edit_form][settings][extra_css]'); + + } + + + + + +} \ No newline at end of file diff --git a/src/Tests/AddThisFieldWebTestBase.php b/src/Tests/AddThisFieldWebTestBase.php new file mode 100644 index 0000000..cb4959d --- /dev/null +++ b/src/Tests/AddThisFieldWebTestBase.php @@ -0,0 +1,151 @@ +administratorAccount = $this->drupalCreateUser($permissions); + parent::drupalLogin($this->administratorAccount); + + // Prepare a new content type where the field will be added. + $this->contentTypeName = strtolower($this->randomMachineName(10)); + $this->drupalGet('admin/structure/types/add'); + $edit = array( + 'name' => $this->contentTypeName, + 'type' => $this->contentTypeName, + ); + $this->drupalPostForm(NULL, $edit, t('Save and manage fields')); + $this->assertText(t('The content type @name has been added.', array('@name' => $this->contentTypeName))); + + // Reset the permission cache. + $create_permission = 'create ' . $this->contentTypeName . ' content'; + $this->checkPermissions(array($create_permission), TRUE); + + // Now that we have a new content type, create a user that has privileges + // on the content type. + $this->authorAccount = $this->drupalCreateUser(array($create_permission)); + } + + /** + * Create a field on the content type created during setUp(). + * + * @param string $type + * The storage field type to create + * @param string $widget_type + * The widget to use when editing this field + * @param int|string $cardinality + * Cardinality of the field. Use -1 to signify 'unlimited.' + * + * @return string + * Name of the field, like field_something + */ + protected function createField($type = 'field_example_rgb', $widget_type = 'field_example_text', $cardinality = '1') { + $this->drupalGet('admin/structure/types/manage/' . $this->contentTypeName . '/fields'); + + // Go to the 'Add field' page. + $this->clickLink('Add field'); + + // Make a name for this field. + $field_name = strtolower($this->randomMachineName(10)); + + // Fill out the field form. + $edit = array( + 'new_storage_type' => $type, + 'field_name' => $field_name, + 'label' => $field_name, + ); + $this->drupalPostForm(NULL, $edit, t('Save and continue')); + + // Fill out the $cardinality form as if we're not using an unlimited number + // of values. + $edit = array( + 'cardinality' => 'number', + 'cardinality_number' => (string) $cardinality, + ); + // If we have -1 for $cardinality, we should change the form's drop-down + // from 'Number' to 'Unlimited.' + if (-1 == $cardinality) { + $edit = array( + 'cardinality' => '-1', + 'cardinality_number' => '1', + ); + } + + // And now we save the cardinality settings. + $this->drupalPostForm(NULL, $edit, t('Save field settings')); + debug( + t('Saved settings for field %field_name with widget %widget_type and cardinality %cardinality', + array( + '%field_name' => $field_name, + '%widget_type' => $widget_type, + '%cardinality' => $cardinality, + ) + ) + ); + $this->assertText(t('Updated field @name field settings.', array('@name' => $field_name))); + + // Set the widget type for the newly created field. + $this->drupalGet('admin/structure/types/manage/' . $this->contentTypeName . '/form-display'); + $edit = array( + 'fields[field_' . $field_name . '][type]' => $widget_type, + ); + $this->drupalPostForm(NULL, $edit, t('Save')); + + return $field_name; + } + +} diff --git a/src/Tests/AddThisPermissionsTest.php b/src/Tests/AddThisPermissionsTest.php new file mode 100644 index 0000000..81364c5 --- /dev/null +++ b/src/Tests/AddThisPermissionsTest.php @@ -0,0 +1,80 @@ +drupalCreateUser(array('administer site configuration')); + $this->drupalLogin($user1); + + $this->drupalGet('admin/config/user-interface/addthis'); + $this->assertRaw(t('Access denied'), + 'A user without administer addthis permission should not be able to access AddThis system settings.'); + + $this->drupalGet('admin/config/user-interface/addthis/advanced'); + $this->assertRaw(t('Access denied'), + 'A user without administer advanced addthis permission should not be able to access AddThis system settings.'); + } + + /** + * Verifies that users can access addthis basic settings page with + * administer addthis settings permission + * - Creates a new user with administer addthis settings + * - verifies user can access addthis basic settings form. + */ + function testAddThisConfigPermissionGranted(){ + // Create user with permission to "administer addthis settings". + $user1 = $this->drupalCreateUser(array('administer addthis settings')); + $this->drupalLogin($user1); + + $this->drupalGet('admin/config/user-interface/addthis'); + //$this->assertNoText(t('Access denied'), 'A user with administer addthis should be able to access the basic addthis configuration page'); + + $this->drupalGet('admin/config/user-interface/addthis/advanced'); + $this->assertText(t('Access denied'), + 'A user without administer advanced addthis permission should not be able to access AddThis system settings.'); + } + + /** + * Verifies that users can access addthis advanced settings with + * administer advanced addthis settings permission. + * - Creates a new user with dminister advanced addthis settings + * - verifies user can access addthis advanced settings. + */ + function testAddThisConfigPermissionAdvancedGranted(){ + // Create user with permission to "administer advanced addthis settings". + $user1 = $this->drupalCreateUser(array('administer advanced addthis settings')); + $this->drupalLogin($user1); + + $this->drupalGet('admin/config/user-interface/addthis/advanced'); + $this->assertNoRaw(t('Access denied'), + 'A user with administer advanced addthis permission should be able to access AddThis system settings.'); + } + + +} \ No newline at end of file diff --git a/src/Util/AddThisJson.php b/src/Util/AddThisJson.php index ebe5c3e..da9bfc9 100644 --- a/src/Util/AddThisJson.php +++ b/src/Util/AddThisJson.php @@ -18,7 +18,8 @@ public function decode($url) { $response = \Drupal::httpClient() ->get($url) ->getBody(TRUE); - } catch (RequestException $e) { + } + catch (RequestException $e) { // Do some stuff in case of the error. } diff --git a/templates/addthis-basic-button.html.twig b/templates/addthis-basic-button.html.twig new file mode 100644 index 0000000..575196f --- /dev/null +++ b/templates/addthis-basic-button.html.twig @@ -0,0 +1,15 @@ +{# +/** + * @file + * Default theme implementation to display a node.. + * Available variables: + * - element: AddThis basic button to be rendered + * + */ +#} + + + + + {{ element }} + diff --git a/templates/addthis-basic-toolbox.html.twig b/templates/addthis-basic-toolbox.html.twig new file mode 100644 index 0000000..5a5944a --- /dev/null +++ b/templates/addthis-basic-toolbox.html.twig @@ -0,0 +1,16 @@ +{# +/** + * @file + * Default theme implementation to display a node.. + * Available variables: + * - element: AddThis Wrapper to be rendered + * + */ + // class="addthis_button_{{ service.service }}" +#} + +
+ {% for service in element.services %} + + {% endfor %} +