Contact Widgets - Version 1.3.3

Version Description

  • October 14, 2016 =

  • Minor bug fixes

  • Remove edit button when previewing in the customizer

Download this release

Release Info

Developer eherman24
Plugin Icon 128x128 Contact Widgets
Version 1.3.3
Comparing to
See all releases

Code changes from version 1.3.2 to 1.3.3

Files changed (51) hide show
  1. contact-widgets.php +1 -1
  2. includes/class-base-widget.php +6 -1
  3. includes/class-contact.php +1 -1
  4. readme.txt +6 -1
  5. trunk/assets/css/admin-ie.css +24 -0
  6. trunk/assets/css/admin-ie.min.css +1 -0
  7. trunk/assets/css/admin.css +95 -0
  8. trunk/assets/css/admin.min.css +1 -0
  9. trunk/assets/css/style.css +30 -0
  10. trunk/assets/css/style.min.css +1 -0
  11. trunk/assets/js/admin.js +176 -0
  12. trunk/assets/js/admin.min.js +1 -0
  13. trunk/assets/js/customize-preview-helper.js +9 -0
  14. trunk/assets/js/customize-preview-helper.min.js +1 -0
  15. trunk/contact-widgets.php +104 -0
  16. trunk/includes/autoload.php +39 -0
  17. trunk/includes/class-base-widget.php +569 -0
  18. trunk/includes/class-contact.php +252 -0
  19. trunk/includes/class-plugin.php +39 -0
  20. trunk/includes/class-social.php +275 -0
  21. trunk/includes/social-networks.php +168 -0
  22. trunk/languages/contact-widgets-da_DK.mo +0 -0
  23. trunk/languages/contact-widgets-de_DE.mo +0 -0
  24. trunk/languages/contact-widgets-el.mo +0 -0
  25. trunk/languages/contact-widgets-es_ES.mo +0 -0
  26. trunk/languages/contact-widgets-es_MX.mo +0 -0
  27. trunk/languages/contact-widgets-fi.mo +0 -0
  28. trunk/languages/contact-widgets-fr_FR.mo +0 -0
  29. trunk/languages/contact-widgets-hi_IN.mo +0 -0
  30. trunk/languages/contact-widgets-id_ID.mo +0 -0
  31. trunk/languages/contact-widgets-it_IT.mo +0 -0
  32. trunk/languages/contact-widgets-ja.mo +0 -0
  33. trunk/languages/contact-widgets-ko_KR.mo +0 -0
  34. trunk/languages/contact-widgets-mr.mo +0 -0
  35. trunk/languages/contact-widgets-ms_MY.mo +0 -0
  36. trunk/languages/contact-widgets-nb_NO.mo +0 -0
  37. trunk/languages/contact-widgets-nl_NL.mo +0 -0
  38. trunk/languages/contact-widgets-pl_PL.mo +0 -0
  39. trunk/languages/contact-widgets-pt_BR.mo +0 -0
  40. trunk/languages/contact-widgets-pt_PT.mo +0 -0
  41. trunk/languages/contact-widgets-ru_RU.mo +0 -0
  42. trunk/languages/contact-widgets-sv_SE.mo +0 -0
  43. trunk/languages/contact-widgets-th.mo +0 -0
  44. trunk/languages/contact-widgets-tl.mo +0 -0
  45. trunk/languages/contact-widgets-tr_TR.mo +0 -0
  46. trunk/languages/contact-widgets-uk.mo +0 -0
  47. trunk/languages/contact-widgets-vi.mo +0 -0
  48. trunk/languages/contact-widgets-zh_CN.mo +0 -0
  49. trunk/languages/contact-widgets-zh_HK.mo +0 -0
  50. trunk/languages/contact-widgets-zh_TW.mo +0 -0
  51. trunk/readme.txt +178 -0
contact-widgets.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Plugin Name: Contact Widgets
4
  * Description: Beautifully display social media and contact information on your website with these simple widgets.
5
- * Version: 1.3.2
6
  * Author: GoDaddy
7
  * Author URI: https://godaddy.com
8
  * Text Domain: contact-widgets
2
  /**
3
  * Plugin Name: Contact Widgets
4
  * Description: Beautifully display social media and contact information on your website with these simple widgets.
5
+ * Version: 1.3.3
6
  * Author: GoDaddy
7
  * Author URI: https://godaddy.com
8
  * Text Domain: contact-widgets
includes/class-base-widget.php CHANGED
@@ -453,7 +453,12 @@ abstract class Base_Widget extends \WP_Widget {
453
 
454
  echo '</ul>';
455
 
456
- if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) && isset( $args['id'] ) ) {
 
 
 
 
 
457
 
458
  // admin-bar.php -> wp_admin_bar_customize_menu()
459
  $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
453
 
454
  echo '</ul>';
455
 
456
+ if (
457
+ ! is_customize_preview()
458
+ && current_user_can( 'edit_theme_options' )
459
+ && current_user_can( 'customize' )
460
+ && isset( $args['id'] )
461
+ ) {
462
 
463
  // admin-bar.php -> wp_admin_bar_customize_menu()
464
  $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
includes/class-contact.php CHANGED
@@ -117,7 +117,7 @@ final class Contact extends Base_Widget {
117
  if ( 'yes' === $instance['map']['value'] && ! empty( $fields['address']['value'] ) ) {
118
 
119
  printf(
120
- '<li class="has-map"><iframe src="//www.google.com/maps?q=%s&output=embed&hl=%s" scrolling="no" frameborder="0"></iframe></li>',
121
  urlencode( trim( strip_tags( $fields['address']['value'] ) ) ),
122
  urlencode( $this->get_google_maps_locale() )
123
  );
117
  if ( 'yes' === $instance['map']['value'] && ! empty( $fields['address']['value'] ) ) {
118
 
119
  printf(
120
+ '<li class="has-map"><iframe src="//www.google.com/maps?q=%s&output=embed&hl=%s"></iframe></li>',
121
  urlencode( trim( strip_tags( $fields['address']['value'] ) ) ),
122
  urlencode( $this->get_google_maps_locale() )
123
  );
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: godaddy, jonathanbardo, fjarrett
3
  Tags: widget, contact, social, sharing, share button, share buttons, share links, social icons, social media, facebook, twitter, google plus, instagram
4
  Requires at least: 4.4.2
5
  Tested up to: 4.6
6
- Stable tag: 1.3.2
7
  License: GPL-2.0
8
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -111,6 +111,11 @@ add_filter( 'wpcw_widget_social_custom_fields', function( $fields, $instance ) {
111
 
112
  == Changelog ==
113
 
 
 
 
 
 
114
  = 1.3.2 - August 16, 2016 =
115
 
116
  * WordPress 4.6 compatibility
3
  Tags: widget, contact, social, sharing, share button, share buttons, share links, social icons, social media, facebook, twitter, google plus, instagram
4
  Requires at least: 4.4.2
5
  Tested up to: 4.6
6
+ Stable tag: 1.3.3
7
  License: GPL-2.0
8
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
9
 
111
 
112
  == Changelog ==
113
 
114
+ = 1.3.3 - October 14, 2016 =
115
+
116
+ * Minor bug fixes
117
+ * Remove edit button when previewing in the customizer
118
+
119
  = 1.3.2 - August 16, 2016 =
120
 
121
  * WordPress 4.6 compatibility
trunk/assets/css/admin-ie.css ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .wpcw-widget .form p {
2
+ margin: 0 0 10px 1px;
3
+ }
4
+ .wpcw-widget .form p.sortable-placeholder {
5
+ margin: 0 0 8px 1px;
6
+ }
7
+ .wpcw-widget .form.ui-sortable p span.dashicons {
8
+ top: 25px;
9
+ }
10
+ .wpcw-widget .form.ui-sortable p.textarea span.dashicons {
11
+ top: 80px;
12
+ }
13
+ .wpcw-widget .ui-sortable.form > p .widefat {
14
+ display: inline;
15
+ }
16
+ /**
17
+ * IE8 fix and woraround
18
+ */
19
+ .ie8 .wpcw-widget .form.ui-sortable p span.dashicons {
20
+ top: 0;
21
+ }
22
+ .ie8 .wpcw-widget-social .icons a.inactive {
23
+ color: #ccc;
24
+ }
trunk/assets/css/admin-ie.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .wpcw-widget .form p{margin:0 0 10px 1px}.wpcw-widget .form p.sortable-placeholder{margin:0 0 8px 1px}.wpcw-widget .form.ui-sortable p span.dashicons{top:25px}.wpcw-widget .form.ui-sortable p.textarea span.dashicons{top:80px}.wpcw-widget .ui-sortable.form>p .widefat{display:inline}.ie8 .wpcw-widget .form.ui-sortable p span.dashicons{top:0}.ie8 .wpcw-widget-social .icons a.inactive{color:#ccc}
trunk/assets/css/admin.css ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Form fields
3
+ */
4
+ .wpcw-widget .form {
5
+ overflow: auto;
6
+ margin-bottom: 1em;
7
+ }
8
+ .wpcw-widget .title {
9
+ margin-top: 1em;
10
+ }
11
+ .wpcw-widget .form p {
12
+ margin: 0 0 10px 0;
13
+ }
14
+ .wpcw-widget .form p.sortable-placeholder {
15
+ margin: 0 0 8px 0;
16
+ }
17
+ .wpcw-widget .form label i {
18
+ margin: 0 7px 0 3px;
19
+ }
20
+ .wpcw-widget .form > p > span {
21
+ display: table;
22
+ width: 100%;
23
+ }
24
+ .wpcw-widget .form > p textarea {
25
+ min-height: 80px;
26
+ resize: none;
27
+ vertical-align: top; /* Bottom margin fix for webkit */
28
+ }
29
+ .wpcw-widget .form.ui-sortable > p .widefat {
30
+ display: table-cell;
31
+ width: 100%; /* Customizer compat */
32
+ }
33
+ .wpcw-widget .form.ui-sortable .wpcw-widget-sortable-handle {
34
+ display: table-cell;
35
+ position: relative;
36
+ width: 25px;
37
+ background-color: #f7f7f7;
38
+ border: 1px solid #ddd;
39
+ border-left: none;
40
+ cursor: row-resize;
41
+ cursor: grab;
42
+ cursor: -moz-grab;
43
+ cursor: -webkit-grab;
44
+
45
+ -webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.04);
46
+ -moz-box-shadow: 0 1px 1px rgba(0,0,0,0.04);
47
+ box-shadow: 0 1px 1px rgba(0,0,0,0.04);
48
+ }
49
+ .wpcw-widget .form.ui-sortable .wpcw-widget-sortable-handle:active,
50
+ .wpcw-widget .form.ui-sortable .ui-sortable-helper * {
51
+ cursor: row-resize;
52
+ cursor: grabbing;
53
+ cursor: -moz-grabbing;
54
+ cursor: -webkit-grabbing;
55
+ }
56
+ .wpcw-widget .form.ui-sortable span.dashicons {
57
+ position: absolute;
58
+ margin: auto;
59
+ top: 0;
60
+ right: 0;
61
+ bottom: 0;
62
+ left: 0;
63
+ overflow: auto;
64
+ font-size: 18px;
65
+ color: #a0a5aa;
66
+ }
67
+ .wpcw-widget .form.ui-sortable span.dashicons:before {
68
+ position: relative;
69
+ top: 1px;
70
+ }
71
+
72
+ /**
73
+ * Default fields
74
+ */
75
+ .wpcw-widget .default-fields {
76
+ display: none;
77
+ }
78
+
79
+ /**
80
+ * Icons
81
+ */
82
+ .wpcw-widget-social .icons {
83
+ margin: 10px 0;
84
+ }
85
+ .wpcw-widget-social .icons a {
86
+ margin: 5px;
87
+ font-size: 20px;
88
+ display: inline-block;
89
+ }
90
+ .wpcw-widget-social .icons a:focus {
91
+ box-shadow: none;
92
+ }
93
+ .wpcw-widget-social .icons a.inactive:not(:hover) {
94
+ color: #ccc;
95
+ }
trunk/assets/css/admin.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .wpcw-widget .form{overflow:auto;margin-bottom:1em}.wpcw-widget .title{margin-top:1em}.wpcw-widget .form p{margin:0 0 10px}.wpcw-widget .form p.sortable-placeholder{margin:0 0 8px}.wpcw-widget .form label i{margin:0 7px 0 3px}.wpcw-widget .form>p>span{display:table;width:100%}.wpcw-widget .form>p textarea{min-height:80px;resize:none;vertical-align:top}.wpcw-widget .form.ui-sortable>p .widefat{display:table-cell;width:100%}.wpcw-widget .form.ui-sortable .wpcw-widget-sortable-handle{display:table-cell;position:relative;width:25px;background-color:#f7f7f7;border:1px solid #ddd;border-left:none;cursor:row-resize;cursor:grab;cursor:-moz-grab;cursor:-webkit-grab;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.04);-moz-box-shadow:0 1px 1px rgba(0,0,0,.04);box-shadow:0 1px 1px rgba(0,0,0,.04)}.wpcw-widget .form.ui-sortable .ui-sortable-helper *,.wpcw-widget .form.ui-sortable .wpcw-widget-sortable-handle:active{cursor:row-resize;cursor:grabbing;cursor:-moz-grabbing;cursor:-webkit-grabbing}.wpcw-widget .form.ui-sortable span.dashicons{position:absolute;margin:auto;top:0;right:0;bottom:0;left:0;overflow:auto;font-size:18px;color:#a0a5aa}.wpcw-widget .form.ui-sortable span.dashicons:before{position:relative;top:1px}.wpcw-widget .default-fields{display:none}.wpcw-widget-social .icons{margin:10px 0}.wpcw-widget-social .icons a{margin:5px;font-size:20px;display:inline-block}.wpcw-widget-social .icons a:focus{box-shadow:none}.wpcw-widget-social .icons a.inactive:not(:hover){color:#ccc}
trunk/assets/css/style.css ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .wpcw-widget-contact ul,
2
+ .wpcw-widget-social ul {
3
+ margin: 0;
4
+ padding: 0;
5
+ list-style: none;
6
+ }
7
+ .wpcw-widget-contact ul li,
8
+ .wpcw-widget-social ul li.has-label {
9
+ padding: 10px 0;
10
+ }
11
+ .wpcw-widget-contact ul li:before,
12
+ .wpcw-widget-contact ul li:after,
13
+ .wpcw-widget-social ul li:before,
14
+ .wpcw-widget-social ul li:after {
15
+ display: none;
16
+ }
17
+ .wpcw-widget-contact ul li div {
18
+ display: inline;
19
+ }
20
+ .wpcw-widget-social ul li:not(.has-label) {
21
+ display: inline-block;
22
+ margin: 0 0.75em 0.75em 0;
23
+ border: none;
24
+ }
25
+ .wpcw-widget-social ul li.has-label a {
26
+ display: block;
27
+ }
28
+ .wpcw-widget-social ul li.has-label span {
29
+ margin-right: 0.25em;
30
+ }
trunk/assets/css/style.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .wpcw-widget-contact ul,.wpcw-widget-social ul{margin:0;padding:0;list-style:none}.wpcw-widget-contact ul li,.wpcw-widget-social ul li.has-label{padding:10px 0}.wpcw-widget-contact ul li:after,.wpcw-widget-contact ul li:before,.wpcw-widget-social ul li:after,.wpcw-widget-social ul li:before{display:none}.wpcw-widget-contact ul li div{display:inline}.wpcw-widget-social ul li:not(.has-label){display:inline-block;margin:0 .75em .75em 0;border:none}.wpcw-widget-social ul li.has-label a{display:block}.wpcw-widget-social ul li.has-label span{margin-right:.25em}
trunk/assets/js/admin.js ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ( function ( $ ) {
2
+
3
+ $.fn.selectString = function ( string ) {
4
+
5
+ var el = $( this )[ 0 ],
6
+ start = el.value.indexOf( string ),
7
+ end = start + string.length;
8
+
9
+ if ( ! el || start < 0 ) {
10
+
11
+ return;
12
+
13
+ } else if ( el.setSelectionRange ) {
14
+
15
+ // Webkit
16
+ el.focus();
17
+ el.setSelectionRange( start, end );
18
+
19
+ } else if ( el.createTextRange ) {
20
+
21
+ var range = el.createTextRange();
22
+
23
+ // IE
24
+ range.collapse( true );
25
+ range.moveEnd( 'character', end );
26
+ range.moveStart( 'character', start );
27
+ range.select();
28
+
29
+ } else if ( el.selectionStart ) {
30
+
31
+ el.selectionStart = start;
32
+ el.selectionEnd = end;
33
+
34
+ }
35
+
36
+ };
37
+
38
+ function start_sortable() {
39
+
40
+ var $contact_form = $( '.wpcw-widget .form' );
41
+
42
+ $contact_form.sortable( {
43
+ items : '> *:not(.not-sortable)',
44
+ handle: '.wpcw-widget-sortable-handle',
45
+ containment: 'parent',
46
+ placeholder: 'sortable-placeholder',
47
+ axis: 'y',
48
+ tolerance: 'pointer',
49
+ forcePlaceholderSize: true,
50
+ cursorAt: { top: 40 },
51
+ stop: function ( e, ui ) {
52
+ // Trigger change for customizer
53
+ $contact_form.find( '.customizer_update' ).val( ui.item.index() ).trigger( 'change' );
54
+ }
55
+ } );
56
+
57
+ }
58
+
59
+ var socialField = {
60
+
61
+ $btn: null,
62
+ $widget: null,
63
+ $template: null,
64
+
65
+ init: function ( e ) {
66
+
67
+ e.preventDefault();
68
+
69
+ var self = socialField;
70
+
71
+ self.$btn = $( this );
72
+ self.$widget = self.$btn.parents( '.wpcw-widget' );
73
+
74
+ // Make sure we don't trigger the animation again on double-click
75
+ if ( self.$widget.find( '.' + self.$btn.data('key') ).is( ':animated' ) ) {
76
+
77
+ return false;
78
+
79
+ }
80
+
81
+ if ( self.$btn.hasClass( 'inactive' ) ) {
82
+
83
+ self.$template = self.$widget.find( '.default-fields' );
84
+ self.$template = $( $.trim( self.$template.clone().html() ) );
85
+
86
+ self.add();
87
+
88
+ return;
89
+
90
+ }
91
+
92
+ self.remove();
93
+
94
+ },
95
+
96
+ add: function () {
97
+
98
+ this.$btn.removeClass( 'inactive' );
99
+
100
+ var data = this.$btn.data();
101
+
102
+ this.$template
103
+ .addClass( data.key )
104
+ .find( 'label' )
105
+ .prop( 'for', data.id );
106
+
107
+ this.$template
108
+ .find( 'input' )
109
+ .prop( 'id', data.id )
110
+ .prop( 'name', data.name )
111
+ .prop( 'value', data.value );
112
+
113
+ this.$template
114
+ .find( 'label span.fa' )
115
+ .prop( 'class', this.$btn.find( 'i' ).attr( 'class' ) );
116
+
117
+ this.$template
118
+ .find( 'label span.text' )
119
+ .text( data.label );
120
+
121
+ this.$template
122
+ .hide()
123
+ .prependTo( this.$widget.find( '.form' ) )
124
+ .stop( true, true )
125
+ .animate( {
126
+ height: 'toggle',
127
+ opacity: 'toggle'
128
+ }, 250 );
129
+
130
+ this.$template.find( 'input' ).selectString( data.select );
131
+
132
+ this.update_customizer();
133
+
134
+ },
135
+
136
+ remove: function () {
137
+
138
+ this.$btn.addClass( 'inactive' );
139
+
140
+ this.$widget
141
+ .find( '.form .' + this.$btn.data( 'key' ) )
142
+ .stop( true, true )
143
+ .animate( {
144
+ height: 'toggle',
145
+ opacity: 'toggle'
146
+ }, 250, function () {
147
+ $( this ).remove();
148
+ } );
149
+
150
+ this.update_customizer();
151
+
152
+ },
153
+
154
+ update_customizer: function () {
155
+
156
+ var count = this.$widget.find( 'div > div' ).length;
157
+
158
+ this.$widget.find( '.customizer_update' ).val( count ).trigger( 'change' );
159
+
160
+ }
161
+
162
+ };
163
+
164
+ $( document ).ready( function ( $ ) {
165
+
166
+ // Social
167
+ $( document ).on( 'click', '.wpcw-widget-social .icons a', socialField.init );
168
+
169
+ // Sortable
170
+ $( document ).on( 'wpcw.change', start_sortable );
171
+ $( document ).on( 'click.widgets-toggle', start_sortable );
172
+ $( document ).on( 'widget-updated', start_sortable );
173
+
174
+ } );
175
+
176
+ } )( jQuery );
trunk/assets/js/admin.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(a){function b(){var b=a(".wpcw-widget .form");b.sortable({items:"> *:not(.not-sortable)",handle:".wpcw-widget-sortable-handle",containment:"parent",placeholder:"sortable-placeholder",axis:"y",tolerance:"pointer",forcePlaceholderSize:!0,cursorAt:{top:40},stop:function(a,c){b.find(".customizer_update").val(c.item.index()).trigger("change")}})}a.fn.selectString=function(b){var c=a(this)[0],d=c.value.indexOf(b),e=d+b.length;if(c&&!(0>d))if(c.setSelectionRange)c.focus(),c.setSelectionRange(d,e);else if(c.createTextRange){var f=c.createTextRange();f.collapse(!0),f.moveEnd("character",e),f.moveStart("character",d),f.select()}else c.selectionStart&&(c.selectionStart=d,c.selectionEnd=e)};var c={$btn:null,$widget:null,$template:null,init:function(b){b.preventDefault();var d=c;return d.$btn=a(this),d.$widget=d.$btn.parents(".wpcw-widget"),d.$widget.find("."+d.$btn.data("key")).is(":animated")?!1:d.$btn.hasClass("inactive")?(d.$template=d.$widget.find(".default-fields"),d.$template=a(a.trim(d.$template.clone().html())),void d.add()):void d.remove()},add:function(){this.$btn.removeClass("inactive");var a=this.$btn.data();this.$template.addClass(a.key).find("label").prop("for",a.id),this.$template.find("input").prop("id",a.id).prop("name",a.name).prop("value",a.value),this.$template.find("label span.fa").prop("class",this.$btn.find("i").attr("class")),this.$template.find("label span.text").text(a.label),this.$template.hide().prependTo(this.$widget.find(".form")).stop(!0,!0).animate({height:"toggle",opacity:"toggle"},250),this.$template.find("input").selectString(a.select),this.update_customizer()},remove:function(){this.$btn.addClass("inactive"),this.$widget.find(".form ."+this.$btn.data("key")).stop(!0,!0).animate({height:"toggle",opacity:"toggle"},250,function(){a(this).remove()}),this.update_customizer()},update_customizer:function(){var a=this.$widget.find("div > div").length;this.$widget.find(".customizer_update").val(a).trigger("change")}};a(document).ready(function(a){a(document).on("click",".wpcw-widget-social .icons a",c.init),a(document).on("wpcw.change",b),a(document).on("click.widgets-toggle",b),a(document).on("widget-updated",b)})}(jQuery);
trunk/assets/js/customize-preview-helper.js ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ ( function ( $, api ) {
2
+
3
+ $( document ).on( 'click', '.wpcw-widgets a.post-edit-link', function() {
4
+
5
+ api.WidgetCustomizerPreview.preview.send( 'focus-widget-control', $( this ).data( 'widget-id' ) );
6
+
7
+ });
8
+
9
+ } )( jQuery, wp.customize );
trunk/assets/js/customize-preview-helper.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(a,b){a(document).on("click",".wpcw-widgets a.post-edit-link",function(){b.WidgetCustomizerPreview.preview.send("focus-widget-control",a(this).data("widget-id"))})}(jQuery,wp.customize);
trunk/contact-widgets.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin Name: Contact Widgets
4
+ * Description: Beautifully display social media and contact information on your website with these simple widgets.
5
+ * Version: 1.3.3
6
+ * Author: GoDaddy
7
+ * Author URI: https://godaddy.com
8
+ * Text Domain: contact-widgets
9
+ * Domain Path: /languages
10
+ * License: GPL-2.0
11
+ * License URI: https://www.gnu.org/licenses/gpl-2.0.html
12
+ *
13
+ * Copyright © 2016 GoDaddy Operating Company, LLC. All Rights Reserved.
14
+ */
15
+
16
+ if ( ! defined( 'ABSPATH' ) ) {
17
+
18
+ exit;
19
+
20
+ }
21
+
22
+ if ( ! class_exists( 'Contact_Widgets' ) ) {
23
+
24
+ final class Contact_Widgets {
25
+
26
+ /**
27
+ * Minimum PHP version
28
+ *
29
+ * @var string
30
+ */
31
+ private $php_min_version = '5.4';
32
+
33
+ /**
34
+ * Plugin assets URL
35
+ *
36
+ * @var string
37
+ */
38
+ public static $assets_url;
39
+
40
+ /**
41
+ * Class constructor
42
+ *
43
+ * @param string $cur_php_version
44
+ */
45
+ public function __construct( $cur_php_version = PHP_VERSION ) {
46
+
47
+ static::$assets_url = plugin_dir_url( __FILE__ ) . 'assets/';
48
+
49
+ $composer_autoloader = __DIR__ . '/vendor/autoload.php';
50
+
51
+ if ( defined( 'WP_CLI' ) && WP_CLI && file_exists( $composer_autoloader ) ) {
52
+
53
+ // This is for enabling codeception
54
+ require_once $composer_autoloader;
55
+
56
+ }
57
+
58
+ add_action( 'plugins_loaded', array( $this, 'i18n' ) );
59
+
60
+ if ( version_compare( $cur_php_version, $this->php_min_version, '<' ) ) {
61
+
62
+ add_action( 'shutdown', array( $this, 'notice' ) );
63
+
64
+ return;
65
+
66
+ }
67
+
68
+ require_once __DIR__ . '/includes/autoload.php';
69
+
70
+ }
71
+
72
+ /**
73
+ * Load languages
74
+ *
75
+ * @action plugins_loaded
76
+ */
77
+ public function i18n() {
78
+
79
+ load_plugin_textdomain( 'contact-widgets', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
80
+
81
+ }
82
+
83
+ /**
84
+ * Display min PHP version notice
85
+ *
86
+ * @action shutdown
87
+ */
88
+ public function notice() {
89
+
90
+ printf(
91
+ '<div class="error"><p>%s</p></div>',
92
+ sprintf(
93
+ __( 'Contact widgets requires PHP version %s or higher. Please deactivate the plugin and contact your system administrator.', 'contact-widgets' ),
94
+ esc_html( $this->php_min_version )
95
+ )
96
+ );
97
+
98
+ }
99
+
100
+ }
101
+
102
+ new Contact_Widgets;
103
+
104
+ }
trunk/includes/autoload.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPCW;
4
+
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+
7
+ exit;
8
+
9
+ }
10
+
11
+ spl_autoload_register( function( $resource ) {
12
+
13
+ if ( 0 !== strpos( $resource, __NAMESPACE__ ) ) {
14
+
15
+ return;
16
+
17
+ }
18
+
19
+ $resource = strtolower(
20
+ str_replace(
21
+ [ __NAMESPACE__ . '\\', '_' ],
22
+ [ '', '-' ],
23
+ $resource
24
+ )
25
+ );
26
+
27
+ $parts = explode( '\\', $resource );
28
+ $name = array_pop( $parts );
29
+ $files = str_replace( '//', '/', glob( sprintf( '%s/%s/*-%s.php', __DIR__, implode( '/', $parts ), $name ) ) );
30
+
31
+ if ( isset( $files[0] ) && is_readable( $files[0] ) ) {
32
+
33
+ require_once $files[0];
34
+
35
+ }
36
+
37
+ } );
38
+
39
+ add_action( 'plugins_loaded', [ __NAMESPACE__ . '\Plugin', 'init' ] );
trunk/includes/class-base-widget.php ADDED
@@ -0,0 +1,569 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPCW;
4
+
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+
7
+ exit;
8
+
9
+ }
10
+
11
+ abstract class Base_Widget extends \WP_Widget {
12
+
13
+ /**
14
+ * Default properties for fields
15
+ *
16
+ * @var array
17
+ */
18
+ protected $field_defaults = [
19
+ 'key' => '',
20
+ 'icon' => '',
21
+ 'class' => 'widefat',
22
+ 'id' => '',
23
+ 'name' => '',
24
+ 'label' => '',
25
+ 'label_after' => false,
26
+ 'description' => '',
27
+ 'type' => 'text',
28
+ 'sanitizer' => 'sanitize_text_field',
29
+ 'escaper' => 'esc_html',
30
+ 'form_callback' => 'render_form_input',
31
+ 'default' => '', // Used mainly for social fields to add default value
32
+ 'value' => '',
33
+ 'placeholder' => '',
34
+ 'sortable' => true,
35
+ 'atts' => '', // Input attributes
36
+ 'show_front_end' => true, // Are we showing this field on the front end?
37
+ 'show_empty' => false, // Show the field even if value is empty
38
+ 'select_options' => [], // Only used if type=select & form_callback=render_form_select
39
+ ];
40
+
41
+ /**
42
+ * Widget base constructor
43
+ *
44
+ * @param string $id_base
45
+ * @param string $name
46
+ * @param array $widget_options
47
+ */
48
+ public function __construct( $id_base, $name, array $widget_options ) {
49
+
50
+ parent::__construct( $id_base, $name, $widget_options );
51
+
52
+ if ( has_action( 'wp_enqueue_scripts', [ $this, 'front_end_enqueue_scripts' ] ) ) {
53
+
54
+ return;
55
+
56
+ }
57
+
58
+ // Enqueue style if widget is active (appears in a sidebar) or if in Customizer preview.
59
+ if ( is_active_widget( false, false, $this->id_base ) || is_customize_preview() ) {
60
+
61
+ add_action( 'wp_enqueue_scripts', [ $this, 'front_end_enqueue_scripts' ] );
62
+
63
+ }
64
+
65
+ }
66
+
67
+ /**
68
+ * Add common ressources needed for the form
69
+ *
70
+ * @param array $instance
71
+ *
72
+ * @return string|void
73
+ */
74
+ public function form( $instance ) {
75
+
76
+ add_action( 'admin_footer', [ $this, 'enqueue_scripts' ] );
77
+ add_action( 'customize_controls_print_footer_scripts', [ $this, 'print_customizer_scripts' ] );
78
+
79
+ ?>
80
+ <script>
81
+ ( function ( $ ) {
82
+
83
+ // This let us know that we appended a new widget to reset sortables
84
+ $( document ).trigger( 'wpcw.change' );
85
+
86
+ } )( jQuery );
87
+ </script>
88
+ <?php
89
+
90
+ }
91
+
92
+ /**
93
+ * Sanitize widget form values as they are saved
94
+ *
95
+ * @param array $new_instance Values just sent to be saved.
96
+ * @param array $old_instance Previously saved values from database.
97
+ *
98
+ * @return array Updated safe values to be saved.
99
+ */
100
+ public function update( $new_instance, $old_instance ) {
101
+
102
+ $fields = $this->get_fields( $old_instance );
103
+
104
+ // Force value for checkbox since they are not posted
105
+ foreach ( $fields as $key => $field ) {
106
+
107
+ if ( 'checkbox' === $field['type'] && ! isset( $new_instance[ $key ]['value'] ) ) {
108
+
109
+ $new_instance[ $key ] = [ 'value' => 'no' ];
110
+
111
+ }
112
+
113
+ }
114
+
115
+ // Starting at 1 since title order is 0
116
+ $order = 1;
117
+
118
+ foreach ( $new_instance as $key => &$instance ) {
119
+
120
+ $sanitizer_callback = $fields[ $key ]['sanitizer'];
121
+
122
+ // Title can't be an array
123
+ if ( 'title' === $key ) {
124
+
125
+ $instance = $sanitizer_callback( $instance['value'] );
126
+
127
+ continue;
128
+
129
+ }
130
+
131
+ $instance['value'] = $sanitizer_callback( $instance['value'] );
132
+ $instance['order'] = $order++;
133
+
134
+ }
135
+
136
+ return $new_instance;
137
+
138
+ }
139
+
140
+ /**
141
+ * Initialize fields for use on front-end of forms
142
+ *
143
+ * @param array $instance
144
+ * @param array $fields (optional)
145
+ * @param bool $ordered (optional)
146
+ *
147
+ * @return array
148
+ */
149
+ protected function get_fields( array $instance, array $fields = [], $ordered = true ) {
150
+
151
+ $order = 0;
152
+
153
+ foreach ( $fields as $key => &$field ) {
154
+
155
+ $common_properties = [
156
+ 'key' => $key,
157
+ 'icon' => $key,
158
+ 'order' => ! empty( $instance[ $key ]['order'] ) ? absint( $instance[ $key ]['order'] ) : $order,
159
+ 'id' => $this->get_field_id( $key ),
160
+ 'name' => $this->get_field_name( $key ) . '[value]',
161
+ 'value' => ! empty( $instance[ $key ]['value'] ) ? $instance[ $key ]['value'] : '',
162
+ ];
163
+
164
+ $common_properties = wp_parse_args( $common_properties, $this->field_defaults );
165
+ $field = wp_parse_args( $field, $common_properties );
166
+
167
+ $default_closure = function( $value ) { return $value; };
168
+
169
+ foreach ( [ 'escaper', 'sanitizer' ] as $key ) {
170
+
171
+ $field[ $key ] = ! is_callable( $field[ $key ] ) ? $default_closure : $field[ $key ];
172
+
173
+ }
174
+
175
+ $order++;
176
+
177
+ }
178
+
179
+ if ( $ordered ) {
180
+
181
+ $fields = $this->order_field( $fields );
182
+
183
+ }
184
+
185
+ return $fields;
186
+
187
+ }
188
+
189
+ /**
190
+ * Order array by field order
191
+ *
192
+ * @param array $fields
193
+ *
194
+ * @return array
195
+ */
196
+ protected function order_field( array $fields ) {
197
+
198
+ uksort( $fields, function( $a, $b ) use ( $fields ) {
199
+
200
+ // We want title first and order of non sortable fields doesn't matter
201
+ if ( ! $fields[ $a ]['sortable'] && 'title' !== $a ) {
202
+
203
+ return 1;
204
+
205
+ }
206
+
207
+ return ( $fields[ $a ]['order'] < $fields[ $b ]['order'] ) ? -1 : 1;
208
+
209
+ } );
210
+
211
+ return $fields;
212
+
213
+ }
214
+
215
+ /**
216
+ * Check if all the fields we show on the front-end are empty
217
+ *
218
+ * @param array $fields
219
+ *
220
+ * @return bool
221
+ */
222
+ protected function is_widget_empty( array $fields ) {
223
+
224
+ foreach ( $fields as $key => $field ) {
225
+
226
+ /**
227
+ * Filter to ignore the title when checking if a widget is empty
228
+ *
229
+ * @since 1.0.0
230
+ *
231
+ * @var bool
232
+ */
233
+ $ignore_title = (bool) apply_filters( 'wpcw_is_widget_empty_ignore_title', false );
234
+
235
+ if ( 'title' === $key && $ignore_title ) {
236
+
237
+ continue;
238
+
239
+ }
240
+
241
+ if ( ! empty( $field['value'] ) && $field['show_front_end'] ) {
242
+
243
+ return false;
244
+
245
+ }
246
+
247
+ }
248
+
249
+ return true;
250
+
251
+ }
252
+
253
+ /**
254
+ * Print current label
255
+ *
256
+ * @param array $field
257
+ */
258
+ protected function print_label( array $field ) {
259
+
260
+ printf(
261
+ ' <label for="%s" title="%s">%s</label>',
262
+ esc_attr( $field['id'] ),
263
+ esc_attr( $field['description'] ),
264
+ esc_html( $field['label'] )
265
+ );
266
+
267
+ }
268
+
269
+ /**
270
+ * Print label and wrapper
271
+ * @param array $field
272
+ */
273
+ protected function before_form_field( array $field ) {
274
+
275
+ $classes = [ $field['type'], $field['key'] ];
276
+
277
+ if ( ! $field['sortable'] ) {
278
+
279
+ $classes[] = 'not-sortable';
280
+
281
+ }
282
+
283
+ if ( $field['label_after'] ) {
284
+
285
+ $classes[] = 'label-after';
286
+
287
+ }
288
+
289
+ printf(
290
+ '<p class="%s">',
291
+ implode( ' ', $classes )
292
+ );
293
+
294
+ if ( ! $field['label_after'] ) {
295
+
296
+ $this->print_label( $field );
297
+
298
+ }
299
+
300
+ if ( $field['sortable'] ) {
301
+
302
+ echo '<span>';
303
+
304
+ }
305
+
306
+ }
307
+
308
+ /**
309
+ * Render input field for admin form
310
+ *
311
+ * @param array $field
312
+ */
313
+ protected function render_form_input( array $field ) {
314
+
315
+ $this->before_form_field( $field );
316
+
317
+ printf(
318
+ '<input class="%s" id="%s" name="%s" type="%s" value="%s" placeholder="%s" autocomplete="off" %s>',
319
+ esc_attr( $field['class'] ),
320
+ esc_attr( $field['id'] ),
321
+ esc_attr( $field['name'] ),
322
+ esc_attr( $field['type'] ),
323
+ esc_attr( $field['value'] ),
324
+ esc_attr( $field['placeholder'] ),
325
+ esc_attr( $field['atts'] )
326
+ );
327
+
328
+ if ( $field['label_after'] ) {
329
+
330
+ $this->print_label( $field );
331
+
332
+ }
333
+
334
+ $this->after_form_field( $field );
335
+
336
+ }
337
+
338
+ /**
339
+ * Render select field
340
+ *
341
+ * @param array $field
342
+ */
343
+ protected function render_form_select( array $field ) {
344
+
345
+ $this->before_form_field( $field );
346
+
347
+ printf(
348
+ '<select class="%s" id="%s" name="%s" autocomplete="off">',
349
+ esc_attr( $field['class'] ),
350
+ esc_attr( $field['id'] ),
351
+ esc_attr( $field['name'] )
352
+ );
353
+
354
+ foreach ( $field['select_options'] as $value => $name ) {
355
+
356
+ printf(
357
+ '<option value="%s" %s>%s</option>',
358
+ $value,
359
+ $field['value'] === $value ? 'selected' : '',
360
+ $name
361
+ );
362
+
363
+ }
364
+
365
+ echo '</select>';
366
+
367
+ if ( $field['label_after'] ) {
368
+
369
+ $this->print_label( $field );
370
+
371
+ }
372
+
373
+ $this->after_form_field( $field );
374
+
375
+ }
376
+
377
+ /**
378
+ * Render textarea field for admin widget form
379
+ *
380
+ * @param array $field
381
+ */
382
+ protected function render_form_textarea( array $field ) {
383
+
384
+ $this->before_form_field( $field );
385
+
386
+ printf(
387
+ '<textarea class="%s" id="%s" name="%s" placeholder="%s">%s</textarea>',
388
+ esc_attr( $field['class'] ),
389
+ esc_attr( $field['id'] ),
390
+ esc_attr( $field['name'] ),
391
+ esc_attr( $field['placeholder'] ),
392
+ esc_textarea( $field['value'] )
393
+ );
394
+
395
+ $this->after_form_field( $field );
396
+
397
+ }
398
+
399
+ /**
400
+ * Close wrapper of form field
401
+ *
402
+ * @param array $field
403
+ */
404
+ protected function after_form_field( array $field ) {
405
+
406
+ if ( $field['sortable'] ) {
407
+
408
+ echo '<span class="wpcw-widget-sortable-handle"><span class="dashicons dashicons-menu"></span></span></span>';
409
+
410
+ }
411
+
412
+ echo '</p>';
413
+
414
+ }
415
+
416
+ /**
417
+ * Print beginning of front-end display
418
+ *
419
+ * @param array $args
420
+ * @param array $fields
421
+ */
422
+ protected function before_widget( array $args, array &$fields ) {
423
+
424
+ $title = array_shift( $fields );
425
+ echo $args['before_widget'];
426
+
427
+ if ( ! empty( $title['value'] ) ) {
428
+
429
+ /**
430
+ * Filter the widget title
431
+ *
432
+ * @since 1.0.0
433
+ *
434
+ * @var string
435
+ */
436
+ $title = (string) apply_filters( 'widget_title', $title['value'] );
437
+
438
+ echo $args['before_title'] . $title . $args['after_title'];
439
+
440
+ }
441
+
442
+ echo '<ul>';
443
+
444
+ }
445
+
446
+ /**
447
+ * Print end of front-end display
448
+ *
449
+ * @param array $args
450
+ * @param array $fields
451
+ */
452
+ protected function after_widget( array $args, array &$fields ) {
453
+
454
+ echo '</ul>';
455
+
456
+ if (
457
+ ! is_customize_preview()
458
+ && current_user_can( 'edit_theme_options' )
459
+ && current_user_can( 'customize' )
460
+ && isset( $args['id'] )
461
+ ) {
462
+
463
+ // admin-bar.php -> wp_admin_bar_customize_menu()
464
+ $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
465
+
466
+ $edit_url = add_query_arg(
467
+ [
468
+ 'autofocus' => [
469
+ 'section' => 'sidebar-widgets-' . $args['id'],
470
+ 'control' => 'widget_' . preg_replace( '/-(\d)/', '[$1]', $args['widget_id'] ),
471
+ ],
472
+ 'url' => urlencode( $current_url ),
473
+ ],
474
+ wp_customize_url()
475
+ );
476
+
477
+ printf(
478
+ '<a class="post-edit-link" data-widget-id="%s" href="%s">%s</a>',
479
+ esc_attr( $args['widget_id'] ),
480
+ esc_url( $edit_url ),
481
+ __( 'Edit' )
482
+ );
483
+
484
+ }
485
+
486
+ echo $args['after_widget'];
487
+
488
+ }
489
+
490
+ /**
491
+ * Helper to output only 'checked' and not checked='checked'
492
+ * IE 9 & 10 don't support the latter
493
+ *
494
+ * @param mixed $helper One of the values to compare
495
+ * @param mixed $current (true) The other value to compare if not just true
496
+ * @param bool $echo Whether to echo or just return the string
497
+ * @return string html attribute or empty string
498
+ */
499
+ public function checked( $helper, $current, $echo = false ) {
500
+
501
+ $result = (string) $helper === (string) $current ? 'checked' : '';
502
+
503
+ if ( $echo ) {
504
+
505
+ echo $result;
506
+
507
+ }
508
+
509
+ return $result;
510
+
511
+ }
512
+
513
+ /**
514
+ * Print footer script and styles
515
+ */
516
+ public function enqueue_scripts() {
517
+
518
+ $suffix = SCRIPT_DEBUG ? '' : '.min';
519
+
520
+ wp_enqueue_style( 'font-awesome', '//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css', [], '4.5.0' );
521
+ wp_enqueue_style( 'wpcw-admin', \Contact_Widgets::$assets_url . "css/admin{$suffix}.css", [ 'font-awesome' ], Plugin::$version );
522
+ wp_enqueue_script( 'wpcw-admin', \Contact_Widgets::$assets_url . "js/admin{$suffix}.js", [ 'jquery' ], Plugin::$version, true );
523
+
524
+ if ( $GLOBALS['is_IE'] ) {
525
+
526
+ wp_enqueue_style( 'wpcw-admin-ie', \Contact_Widgets::$assets_url . "css/admin-ie{$suffix}.css", [ 'wpcw-admin' ], Plugin::$version );
527
+
528
+ }
529
+
530
+ }
531
+
532
+ /**
533
+ * Print customizer script
534
+ */
535
+ public function print_customizer_scripts() {
536
+
537
+ $this->enqueue_scripts();
538
+
539
+ wp_print_styles( [ 'font-awesome', 'wpcw-admin', 'wpcw-admin-ie' ] );
540
+ wp_print_scripts( 'wpcw-admin' );
541
+
542
+ }
543
+
544
+ /**
545
+ * Enqueue scripts and styles for front-end use
546
+ *
547
+ * @action wp_enqueue_scripts
548
+ */
549
+ public function front_end_enqueue_scripts() {
550
+
551
+ $suffix = SCRIPT_DEBUG ? '' : '.min';
552
+
553
+ wp_enqueue_style( 'wpcw', \Contact_Widgets::$assets_url . "css/style{$suffix}.css", [], Plugin::$version );
554
+
555
+ if ( is_customize_preview() ) {
556
+
557
+ if ( ! wp_script_is( 'jquery', 'enqueued' ) ) {
558
+
559
+ wp_enqueue_script( 'jquery' );
560
+
561
+ }
562
+
563
+ wp_enqueue_script( 'wpcw-helper', \Contact_Widgets::$assets_url . "js/customize-preview-helper{$suffix}.js", [ 'jquery' ], Plugin::$version, true );
564
+
565
+ }
566
+
567
+ }
568
+
569
+ }
trunk/includes/class-contact.php ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPCW;
4
+
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+
7
+ exit;
8
+
9
+ }
10
+
11
+ final class Contact extends Base_Widget {
12
+
13
+ /**
14
+ * Widget constructor
15
+ */
16
+ public function __construct() {
17
+
18
+ $widget_options = [
19
+ 'classname' => 'wpcw-widgets wpcw-widget-contact',
20
+ 'description' => __( 'Display your contact information.', 'contact-widgets' ),
21
+ 'customize_selective_refresh' => true,
22
+ ];
23
+
24
+ parent::__construct(
25
+ 'wpcw_contact',
26
+ __( 'Contact Details', 'contact-widgets' ),
27
+ $widget_options
28
+ );
29
+
30
+ }
31
+
32
+ /**
33
+ * Widget form fields
34
+ *
35
+ * @param array $instance The widget options
36
+ *
37
+ * @return string|void
38
+ */
39
+ public function form( $instance ) {
40
+
41
+ parent::form( $instance );
42
+
43
+ $fields = $this->get_fields( $instance );
44
+
45
+ echo '<div class="wpcw-widget wpcw-widget-contact">';
46
+
47
+ echo '<div class="title">';
48
+
49
+ // Title field
50
+ $this->render_form_input( array_shift( $fields ) );
51
+
52
+ echo '</div>';
53
+
54
+ echo '<div class="form">';
55
+
56
+ foreach ( $fields as $key => $field ) {
57
+
58
+ $method = $field['form_callback'];
59
+
60
+ if ( is_callable( [ $this, $method ] ) ) {
61
+
62
+ $this->$method( $field );
63
+
64
+ }
65
+
66
+ }
67
+
68
+ // Workaround customizer refresh @props @westonruter
69
+ echo '<input class="customizer_update" type="hidden" value="">';
70
+
71
+ echo '</div>'; // End form
72
+
73
+ echo '</div>'; // End wpcw-widget-contact
74
+
75
+ }
76
+
77
+ /**
78
+ * Front-end display
79
+ *
80
+ * @param array $args
81
+ * @param array $instance
82
+ */
83
+ public function widget( $args, $instance ) {
84
+
85
+ $fields = $this->get_fields( $instance );
86
+
87
+ if ( $this->is_widget_empty( $fields ) ) {
88
+
89
+ return;
90
+
91
+ }
92
+
93
+ $this->before_widget( $args, $fields );
94
+
95
+ $display_labels = ( 'yes' === $instance['labels']['value'] );
96
+
97
+ foreach ( $fields as $field ) {
98
+
99
+ if ( empty( $field['value'] ) || ! $field['show_front_end'] ) {
100
+
101
+ continue;
102
+
103
+ }
104
+
105
+ $escape_callback = $field['escaper'];
106
+ $label = str_replace( ':', '', $field['label'] );
107
+
108
+ printf(
109
+ '<li class="%s">%s<div>%s</div></li>',
110
+ $display_labels ? 'has-label' : 'no-label',
111
+ $display_labels ? sprintf( '<strong>%s</strong><br>', esc_html( $label ) ) : '',
112
+ $escape_callback( $field['value'] )
113
+ );
114
+
115
+ }
116
+
117
+ if ( 'yes' === $instance['map']['value'] && ! empty( $fields['address']['value'] ) ) {
118
+
119
+ printf(
120
+ '<li class="has-map"><iframe src="//www.google.com/maps?q=%s&output=embed&hl=%s"></iframe></li>',
121
+ urlencode( trim( strip_tags( $fields['address']['value'] ) ) ),
122
+ urlencode( $this->get_google_maps_locale() )
123
+ );
124
+
125
+ }
126
+
127
+ $this->after_widget( $args, $fields );
128
+
129
+ }
130
+
131
+ /**
132
+ * Initialize fields for use on front-end of forms
133
+ *
134
+ * @param array $instance
135
+ * @param array $fields
136
+ * @param bool $ordered
137
+ *
138
+ * @return array
139
+ */
140
+ protected function get_fields( array $instance, array $fields = [], $ordered = true ) {
141
+
142
+ $fields = [
143
+ 'title' => [
144
+ 'label' => __( 'Title:', 'contact-widgets' ),
145
+ 'description' => __( 'The title of widget. Leave empty for no title.', 'contact-widgets' ),
146
+ 'value' => ! empty( $instance['title'] ) ? $instance['title'] : '',
147
+ 'sortable' => false,
148
+ ],
149
+ 'email' => [
150
+ 'label' => __( 'Email:', 'contact-widgets' ),
151
+ 'type' => 'email',
152
+ 'sanitizer' => 'sanitize_email',
153
+ 'escaper' => function( $value ) {
154
+ // Work around until https://core.trac.wordpress.org/ticket/32787
155
+ return sprintf( '<a href="mailto:%1$s">%1$s</a>', antispambot( $value ) );
156
+ },
157
+ 'description' => __( 'An email address where website vistors can contact you.', 'contact-widgets' ),
158
+ ],
159
+ 'phone' => [
160
+ 'label' => __( 'Phone:', 'contact-widgets' ),
161
+ 'type' => 'text',
162
+ 'description' => __( 'A phone number that website vistors can call if they have questions.', 'contact-widgets' ),
163
+ ],
164
+ 'fax' => [
165
+ 'label' => __( 'Fax:', 'contact-widgets' ),
166
+ 'type' => 'text',
167
+ 'description' => __( 'A fax number that website vistors can use to send important documents.', 'contact-widgets' ),
168
+ ],
169
+ 'address' => [
170
+ 'label' => __( 'Address:', 'contact-widgets' ),
171
+ 'type' => 'textarea',
172
+ 'sanitizer' => function( $value ) { return current_user_can( 'unfiltered_html' ) ? $value : wp_kses_post( stripslashes( $value ) ); },
173
+ 'escaper' => function( $value ) { return nl2br( apply_filters( 'widget_text', $value ) ); },
174
+ 'form_callback' => 'render_form_textarea',
175
+ 'description' => __( 'A physical address where website vistors can go to visit you in person.', 'contact-widgets' ),
176
+ ],
177
+ 'labels' => [
178
+ 'label' => __( 'Display labels?', 'contact-widgets' ),
179
+ 'class' => '',
180
+ 'label_after' => true,
181
+ 'type' => 'checkbox',
182
+ 'sortable' => false,
183
+ 'value' => 'yes',
184
+ 'atts' => $this->checked( 'yes', isset( $instance['labels']['value'] ) ? $instance['labels']['value'] : 'yes' ),
185
+ 'show_front_end' => false,
186
+ ],
187
+ 'map' => [
188
+ 'label' => __( 'Display map of address?', 'contact-widgets' ),
189
+ 'class' => '',
190
+ 'label_after' => true,
191
+ 'type' => 'checkbox',
192
+ 'sortable' => false,
193
+ 'value' => 'yes',
194
+ 'atts' => $this->checked( 'yes', isset( $instance['map']['value'] ) ? $instance['map']['value'] : 'yes' ),
195
+ 'show_front_end' => false,
196
+ ],
197
+ ];
198
+
199
+ $fields = apply_filters( 'wpcw_widget_contact_custom_fields', $fields, $instance );
200
+ $fields = parent::get_fields( $instance, $fields );
201
+
202
+ /**
203
+ * Filter the contact fields
204
+ *
205
+ * @since 1.0.0
206
+ *
207
+ * @var array
208
+ */
209
+ return (array) apply_filters( 'wpcw_widget_contact_fields', $fields, $instance );
210
+
211
+ }
212
+
213
+ /**
214
+ * Get the current locale in Google Maps API format
215
+ *
216
+ * @link https://developers.google.com/maps/faq#languagesupport
217
+ *
218
+ * @return string
219
+ */
220
+ protected function get_google_maps_locale() {
221
+
222
+ $locale = get_locale();
223
+
224
+ switch ( $locale ) {
225
+
226
+ case 'en_AU' :
227
+ case 'en_GB' :
228
+ case 'pt_BR' :
229
+ case 'pt_PT' :
230
+ case 'zh_TW' :
231
+
232
+ $locale = str_replace( '_', '-', $locale );
233
+
234
+ break;
235
+
236
+ case 'zh_CH' :
237
+
238
+ $locale = 'zh-CN';
239
+
240
+ break;
241
+
242
+ default :
243
+
244
+ $locale = substr( $locale, 0, 2 );
245
+
246
+ }
247
+
248
+ return $locale;
249
+
250
+ }
251
+
252
+ }
trunk/includes/class-plugin.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPCW;
4
+
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+
7
+ exit;
8
+
9
+ }
10
+
11
+ class Plugin {
12
+
13
+ /**
14
+ * Plugin version
15
+ *
16
+ * @var string
17
+ */
18
+ public static $version = '1.0.1';
19
+
20
+ /**
21
+ * Class constructor
22
+ */
23
+ public static function init() {
24
+
25
+ add_action( 'widgets_init', [ get_called_class(), 'register_widgets' ] );
26
+
27
+ }
28
+
29
+ /**
30
+ * Register our custom widget using the api
31
+ */
32
+ public static function register_widgets() {
33
+
34
+ register_widget( __NAMESPACE__ . '\Contact' );
35
+ register_widget( __NAMESPACE__ . '\Social' );
36
+
37
+ }
38
+
39
+ }
trunk/includes/class-social.php ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPCW;
4
+
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+
7
+ exit;
8
+
9
+ }
10
+
11
+ final class Social extends Base_Widget {
12
+
13
+ /**
14
+ * Widget constructor
15
+ */
16
+ public function __construct() {
17
+
18
+ $widget_options = [
19
+ 'classname' => 'wpcw-widgets wpcw-widget-social',
20
+ 'description' => __( 'Display links to your social media profiles.', 'contact-widgets' ),
21
+ 'customize_selective_refresh' => true,
22
+ ];
23
+
24
+ parent::__construct(
25
+ 'wpcw_social',
26
+ __( 'Social Profiles', 'contact-widgets' ),
27
+ $widget_options
28
+ );
29
+
30
+ }
31
+
32
+ /**
33
+ * Widget form fields
34
+ *
35
+ * @param array $instance
36
+ *
37
+ * @return string|void
38
+ */
39
+ public function form( $instance ) {
40
+
41
+ parent::form( $instance );
42
+
43
+ $fields = $this->get_fields( $instance );
44
+ $title_field = array_shift( $fields );
45
+
46
+ echo '<div class="wpcw-widget wpcw-widget-social">';
47
+
48
+ echo '<div class="title">';
49
+
50
+ // Title field
51
+ $this->render_form_input( $title_field );
52
+
53
+ echo '</div>';
54
+
55
+ echo '<div class="icons">';
56
+
57
+ foreach ( $fields as $key => $field ) {
58
+
59
+ if ( ! isset( $field['social'] ) ) {
60
+
61
+ continue;
62
+
63
+ }
64
+
65
+ printf(
66
+ '<a href="#"
67
+ class="%s"
68
+ title="%s"
69
+ data-key="%s"
70
+ data-value="%s"
71
+ data-select="%s"
72
+ data-name="%s"
73
+ data-id="%s"
74
+ data-label="%s">
75
+ <i class="fa fa-%s"></i>
76
+ </a>',
77
+ empty( $field['value'] ) ? 'inactive' : '',
78
+ esc_attr( $field['label'] ),
79
+ esc_attr( $key ),
80
+ esc_attr( $field['default'] ),
81
+ esc_attr( $field['select'] ),
82
+ esc_attr( $field['name'] ),
83
+ esc_attr( $field['id'] ),
84
+ esc_attr( $field['label'] ),
85
+ esc_attr( $field['icon'] )
86
+ );
87
+
88
+ }
89
+
90
+ echo '</div>';
91
+
92
+ echo '<div class="form">';
93
+
94
+ $fields = $this->order_field( $fields );
95
+
96
+ foreach ( $fields as $key => $field ) {
97
+
98
+ $method = $field['form_callback'];
99
+
100
+ if (
101
+ is_callable( [ $this, $method ] )
102
+ &&
103
+ ( ! empty( $field['value'] ) || $field['show_empty'] )
104
+ ) {
105
+
106
+ $this->$method( $field );
107
+
108
+ }
109
+
110
+ }
111
+
112
+ // Workaround customizer refresh @props @westonruter
113
+ echo '<input class="customizer_update" type="hidden" value="">';
114
+
115
+ echo '</div>'; // End form
116
+
117
+ echo '<div class="default-fields">';
118
+
119
+ // Template form for JS use
120
+ $this->render_form_input( $this->field_defaults + [ 'social' => true ] );
121
+
122
+ echo '</div>'; // End default-fields
123
+
124
+ echo '</div>'; // End wpcw-widget-social
125
+
126
+ }
127
+
128
+ /**
129
+ * Front-end display
130
+ *
131
+ * @param array $args
132
+ * @param array $instance
133
+ */
134
+ public function widget( $args, $instance ) {
135
+
136
+ $fields = $this->get_fields( $instance, [], true );
137
+
138
+ if ( $this->is_widget_empty( $fields ) ) {
139
+
140
+ return;
141
+
142
+ }
143
+
144
+ $this->before_widget( $args, $fields );
145
+
146
+ $display_labels = ( 'yes' === $instance['labels']['value'] );
147
+
148
+ foreach ( $fields as $field ) {
149
+
150
+ if ( empty( $field['value'] ) || ! $field['show_front_end'] ) {
151
+
152
+ continue;
153
+
154
+ }
155
+
156
+ $escape_callback = $field['escaper'];
157
+
158
+ printf(
159
+ '<li class="%s"><a href="%s" target="%s" title="%s"><span class="fa fa-%s fa-%s"></span>%s</a></li>',
160
+ $display_labels ? 'has-label' : 'no-label',
161
+ $escape_callback( $field['value'] ),
162
+ esc_attr( $field['target'] ),
163
+ sprintf( esc_attr_x( 'Visit %1$s on %2$s', '1. Title of website (e.g. My Cat Blog), 2. Name of social network (e.g. Facebook)', 'contact-widgets' ), get_bloginfo( 'name' ), $field['label'] ),
164
+ isset( $fields['icon_size']['value'] ) ? esc_attr( $fields['icon_size']['value'] ) : '2x',
165
+ esc_attr( $field['icon'] ),
166
+ $display_labels ? esc_html( $field['label'] ) : ''
167
+ );
168
+
169
+ }
170
+
171
+ $this->after_widget( $args, $fields );
172
+
173
+ }
174
+
175
+ /**
176
+ * Enqueue scripts and styles for front-end use
177
+ *
178
+ * @action wp_enqueue_scripts
179
+ */
180
+ public function front_end_enqueue_scripts() {
181
+
182
+ wp_enqueue_style( 'font-awesome', '//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css', [], '4.5.0' );
183
+
184
+ parent::front_end_enqueue_scripts();
185
+
186
+ }
187
+
188
+ /**
189
+ * Initialize fields for use on front-end of forms
190
+ *
191
+ * @param array $instance
192
+ * @param array $fields (optional)
193
+ * @param bool $ordered (optional)
194
+ *
195
+ * @return array
196
+ */
197
+ protected function get_fields( array $instance, array $fields = [], $ordered = false ) {
198
+
199
+ include 'social-networks.php';
200
+
201
+ foreach ( $fields as $key => &$field ) {
202
+
203
+ $default = [
204
+ 'sanitizer' => 'esc_url_raw',
205
+ 'escaper' => 'esc_url',
206
+ 'select' => '',
207
+ 'social' => true,
208
+ 'target' => '_blank',
209
+ ];
210
+
211
+ $field = wp_parse_args( $field, $default );
212
+
213
+ }
214
+
215
+ $title = [
216
+ 'title' => [
217
+ 'label' => __( 'Title:', 'contact-widgets' ),
218
+ 'description' => __( 'The title of widget. Leave empty for no title.', 'contact-widgets' ),
219
+ 'value' => ! empty( $instance['title'] ) ? $instance['title'] : '',
220
+ 'sortable' => false,
221
+ ],
222
+ ];
223
+
224
+ // Prepend title field to the array
225
+ $fields = $title + $fields;
226
+
227
+ $fields['labels'] = [
228
+ 'label' => __( 'Display labels?', 'contact-widgets' ),
229
+ 'class' => '',
230
+ 'label_after' => true,
231
+ 'type' => 'checkbox',
232
+ 'sortable' => false,
233
+ 'value' => 'yes',
234
+ 'atts' => $this->checked( 'yes', isset( $instance['labels']['value'] ) ? $instance['labels']['value'] : 'no' ),
235
+ 'show_front_end' => false,
236
+ ];
237
+
238
+ $fields = apply_filters( 'wpcw_widget_social_custom_fields', $fields, $instance );
239
+ $fields = parent::get_fields( $instance, $fields, $ordered );
240
+
241
+ /**
242
+ * Filter the social fields
243
+ *
244
+ * @since 1.0.0
245
+ *
246
+ * @var array
247
+ */
248
+ return (array) apply_filters( 'wpcw_widget_social_fields', $fields, $instance );
249
+
250
+ }
251
+
252
+ /**
253
+ * Print label and wrapper
254
+ *
255
+ * @param array $field
256
+ */
257
+ protected function print_label( array $field ) {
258
+
259
+ if ( ! isset( $field['social'] ) ) {
260
+
261
+ parent::print_label( $field );
262
+ return;
263
+
264
+ }
265
+
266
+ printf(
267
+ '<label for="%s"><span class="fa fa-%s"></span> <span class="text">%s</span></label>',
268
+ esc_attr( $field['id'] ),
269
+ esc_attr( $field['icon'] ),
270
+ esc_html( $field['label'] )
271
+ );
272
+
273
+ }
274
+
275
+ }
trunk/includes/social-networks.php ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+
5
+ exit;
6
+
7
+ }
8
+
9
+ $username = esc_attr_x( 'username', 'Must be lowercase and use url-safe characters', 'contact-widgets' );
10
+ $channel = esc_attr_x( 'channel', 'Must be lowercase and use url-safe characters', 'contact-widgets' );
11
+ $company = esc_attr_x( 'company', 'Must be lowercase and use url-safe characters', 'contact-widgets' );
12
+ $board = esc_attr_x( 'board', 'Must be lowercase and use url-safe characters', 'contact-widgets' );
13
+
14
+ $fields = [
15
+ 'facebook' => [
16
+ 'icon' => 'facebook-official',
17
+ 'label' => __( 'Facebook', 'contact-widgets' ),
18
+ 'default' => "https://www.facebook.com/{$username}",
19
+ 'select' => $username,
20
+ ],
21
+ 'twitter' => [
22
+ 'label' => __( 'Twitter', 'contact-widgets' ),
23
+ 'default' => "https://twitter.com/{$username}",
24
+ 'select' => $username,
25
+ ],
26
+ 'googleplus' => [
27
+ 'icon' => 'google-plus',
28
+ 'label' => __( 'Google+', 'contact-widgets' ),
29
+ 'default' => "https://google.com/+{$username}",
30
+ 'select' => $username,
31
+ ],
32
+ 'linkedin' => [
33
+ 'icon' => 'linkedin-square',
34
+ 'label' => __( 'LinkedIn', 'contact-widgets' ),
35
+ 'default' => "https://www.linkedin.com/in/{$username}",
36
+ 'select' => $username,
37
+ ],
38
+ 'rss' => [
39
+ 'label' => __( 'RSS feed', 'contact-widgets' ),
40
+ 'default' => get_feed_link(),
41
+ ],
42
+ 'pinterest' => [
43
+ 'label' => __( 'Pinterest', 'contact-widgets' ),
44
+ 'default' => "https://www.pinterest.com/{$username}",
45
+ 'select' => $username,
46
+ ],
47
+ 'youtube' => [
48
+ 'label' => __( 'YouTube', 'contact-widgets' ),
49
+ 'default' => "https://www.youtube.com/user/{$username}",
50
+ 'select' => $username,
51
+ ],
52
+ 'vimeo' => [
53
+ 'label' => __( 'Vimeo', 'contact-widgets' ),
54
+ 'default' => "https://vimeo.com/{$username}",
55
+ 'select' => $username,
56
+ ],
57
+ 'flickr' => [
58
+ 'label' => __( 'Flickr', 'contact-widgets' ),
59
+ 'default' => "https://www.flickr.com/photos/{$username}",
60
+ 'select' => $username,
61
+ ],
62
+ '500px' => [
63
+ 'label' => __( '500px', 'contact-widgets' ),
64
+ 'default' => "https://www.500px.com/{$username}",
65
+ 'select' => $username,
66
+ ],
67
+ 'foursquare' => [
68
+ 'label' => __( 'Foursquare', 'contact-widgets' ),
69
+ 'default' => "https://foursquare.com/{$username}",
70
+ 'select' => $username,
71
+ ],
72
+ 'github' => [
73
+ 'label' => __( 'GitHub', 'contact-widgets' ),
74
+ 'default' => "https://github.com/{$username}",
75
+ 'select' => $username,
76
+ ],
77
+ 'slack' => [
78
+ 'label' => __( 'Slack', 'contact-widgets' ),
79
+ 'default' => "https://{$channel}.slack.com/",
80
+ 'select' => $channel,
81
+ ],
82
+ 'skype' => [
83
+ 'label' => __( 'Skype', 'contact-widgets' ),
84
+ 'default' => "skype:{$username}?chat",
85
+ 'sanitizer' => 'esc_attr',
86
+ 'escaper' => 'esc_attr',
87
+ 'select' => $username,
88
+ ],
89
+ 'soundcloud' => [
90
+ 'label' => __( 'SoundCloud', 'contact-widgets' ),
91
+ 'default' => "https://soundcloud.com/{$username}",
92
+ 'select' => $username,
93
+ ],
94
+ 'tripadvisor' => [
95
+ 'label' => __( 'TripAdvisor', 'contact-widgets' ),
96
+ 'default' => 'https://www.tripadvisor.com/',
97
+ ],
98
+ 'wordpress' => [
99
+ 'label' => __( 'WordPress', 'contact-widgets' ),
100
+ 'default' => "https://profiles.wordpress.org/{$username}",
101
+ 'select' => $username,
102
+ ],
103
+ 'yelp' => [
104
+ 'label' => __( 'Yelp', 'contact-widgets' ),
105
+ 'default' => "http://www.yelp.com/biz/{$company}",
106
+ 'select' => $company,
107
+ ],
108
+ 'amazon' => [
109
+ 'label' => __( 'Amazon', 'contact-widgets' ),
110
+ 'default' => 'https://www.amazon.com/',
111
+ ],
112
+ 'instagram' => [
113
+ 'label' => __( 'Instagram', 'contact-widgets' ),
114
+ 'default' => "https://www.instagram.com/{$username}",
115
+ 'select' => $username,
116
+ ],
117
+ 'vine' => [
118
+ 'label' => __( 'Vine', 'contact-widgets' ),
119
+ 'default' => "https://vine.co/{$username}",
120
+ 'select' => $username,
121
+ ],
122
+ 'reddit' => [
123
+ 'label' => __( 'reddit', 'contact-widgets' ),
124
+ 'default' => "https://www.reddit.com/user/{$username}",
125
+ 'select' => $username,
126
+ ],
127
+ 'xing' => [
128
+ 'label' => __( 'XING', 'contact-widgets' ),
129
+ 'default' => 'https://www.xing.com/',
130
+ ],
131
+ 'tumblr' => [
132
+ 'label' => __( 'Tumblr', 'contact-widgets' ),
133
+ 'default' => "https://{$username}.tumblr.com/",
134
+ 'select' => $username,
135
+ ],
136
+ 'whatsapp' => [
137
+ 'label' => __( 'WhatsApp', 'contact-widgets' ),
138
+ 'default' => 'https://www.whatsapp.com/',
139
+ ],
140
+ 'wechat' => [
141
+ 'label' => __( 'WeChat', 'contact-widgets' ),
142
+ 'default' => 'http://www.wechat.com/',
143
+ ],
144
+ 'medium' => [
145
+ 'label' => __( 'Medium', 'contact-widgets' ),
146
+ 'default' => "https://medium.com/@{$username}",
147
+ 'select' => $username,
148
+ ],
149
+ 'dribbble' => [
150
+ 'label' => __( 'Dribbble', 'contact-widgets' ),
151
+ 'default' => "https://dribbble.com/{$username}",
152
+ 'select' => $username,
153
+ ],
154
+ 'twitch' => [
155
+ 'label' => __( 'Twitch', 'contact-widgets' ),
156
+ 'default' => "https://www.twitch.tv/{$username}",
157
+ 'select' => $username,
158
+ ],
159
+ 'vk' => [
160
+ 'label' => __( 'VK', 'contact-widgets' ),
161
+ 'default' => 'https://vk.com/',
162
+ ],
163
+ 'trello' => [
164
+ 'label' => __( 'Trello', 'contact-widgets' ),
165
+ 'default' => "https://trello.com/b/{$board}",
166
+ 'select' => $board,
167
+ ],
168
+ ];
trunk/languages/contact-widgets-da_DK.mo ADDED
Binary file
trunk/languages/contact-widgets-de_DE.mo ADDED
Binary file
trunk/languages/contact-widgets-el.mo ADDED
Binary file
trunk/languages/contact-widgets-es_ES.mo ADDED
Binary file
trunk/languages/contact-widgets-es_MX.mo ADDED
Binary file
trunk/languages/contact-widgets-fi.mo ADDED
Binary file
trunk/languages/contact-widgets-fr_FR.mo ADDED
Binary file
trunk/languages/contact-widgets-hi_IN.mo ADDED
Binary file
trunk/languages/contact-widgets-id_ID.mo ADDED
Binary file
trunk/languages/contact-widgets-it_IT.mo ADDED
Binary file
trunk/languages/contact-widgets-ja.mo ADDED
Binary file
trunk/languages/contact-widgets-ko_KR.mo ADDED
Binary file
trunk/languages/contact-widgets-mr.mo ADDED
Binary file
trunk/languages/contact-widgets-ms_MY.mo ADDED
Binary file
trunk/languages/contact-widgets-nb_NO.mo ADDED
Binary file
trunk/languages/contact-widgets-nl_NL.mo ADDED
Binary file
trunk/languages/contact-widgets-pl_PL.mo ADDED
Binary file
trunk/languages/contact-widgets-pt_BR.mo ADDED
Binary file
trunk/languages/contact-widgets-pt_PT.mo ADDED
Binary file
trunk/languages/contact-widgets-ru_RU.mo ADDED
Binary file
trunk/languages/contact-widgets-sv_SE.mo ADDED
Binary file
trunk/languages/contact-widgets-th.mo ADDED
Binary file
trunk/languages/contact-widgets-tl.mo ADDED
Binary file
trunk/languages/contact-widgets-tr_TR.mo ADDED
Binary file
trunk/languages/contact-widgets-uk.mo ADDED
Binary file
trunk/languages/contact-widgets-vi.mo ADDED
Binary file
trunk/languages/contact-widgets-zh_CN.mo ADDED
Binary file
trunk/languages/contact-widgets-zh_HK.mo ADDED
Binary file
trunk/languages/contact-widgets-zh_TW.mo ADDED
Binary file
trunk/readme.txt ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Contact Widgets ===
2
+ Contributors: godaddy, jonathanbardo, fjarrett
3
+ Tags: widget, contact, social, sharing, share button, share buttons, share links, social icons, social media, facebook, twitter, google plus, instagram
4
+ Requires at least: 4.4.2
5
+ Tested up to: 4.7
6
+ Stable tag: 1.3.3
7
+ License: GPL-2.0
8
+ License URI: https://www.gnu.org/licenses/gpl-2.0.html
9
+
10
+ Beautifully display social media and contact information on your website with these simple widgets.
11
+
12
+ == Description ==
13
+
14
+ **Note: This plugin requires PHP 5.4 or higher to be activated.**
15
+
16
+ This plugin adds two new widgets to your WordPress website:
17
+
18
+ * Contact Information: Displays your contact information including email address, phone number, fax and physical address (including a map).
19
+ * Social Media Profiles: Displays your social media profiles in an attractive, intuitive way.
20
+
21
+ Both widgets are compatible with the WordPress Customizer and will automatically refresh when changes are made.
22
+
23
+ **Languages Supported:**
24
+
25
+ * English
26
+ * Dansk
27
+ * Deutsch
28
+ * Ελληνικά
29
+ * Español
30
+ * Español de México
31
+ * Suomi
32
+ * Français
33
+ * हिन्दी
34
+ * Bahasa Indonesia
35
+ * Italiano
36
+ * 日本語
37
+ * 한국어
38
+ * मराठी
39
+ * Bahasa Melayu
40
+ * Norsk bokmål
41
+ * Nederlands
42
+ * Polski
43
+ * Português do Brasil
44
+ * Português
45
+ * Русский
46
+ * Svenska
47
+ * ไทย
48
+ * Tagalog
49
+ * Türkçe
50
+ * Українська
51
+ * Tiếng Việt
52
+ * 简体中文
53
+ * 香港中文版
54
+ * 繁體中文
55
+
56
+ **Improvement? Bugs?**
57
+
58
+ Please fill out an issue [here](https://github.com/godaddy/wp-contact-widgets/issues).
59
+
60
+ == Screenshots ==
61
+
62
+ 1. Contact widget
63
+ 2. Social widget
64
+ 3. Twenty Sixteen theme showing both widgets
65
+
66
+ == Frequently Asked Questions ==
67
+
68
+ ### How do I add additional fields to the contact widget?
69
+
70
+ Adding additional fields to the contact widget is as simple as adding a WordPress filter.
71
+
72
+ Here is an example:
73
+ <pre lang="php">
74
+ add_filter( 'wpcw_widget_contact_custom_fields', function( $fields, $instance ) {
75
+
76
+ $fields['cellphone'] = [
77
+ 'order' => 2,
78
+ 'label' => __( 'Cellphone:', 'YOURTEXTDOMAIN' ),
79
+ 'type' => 'text',
80
+ 'description' => __( 'A cellphone number that website vistors can call if they have questions.', 'YOURTEXTDOMAIN' ),
81
+ ];
82
+
83
+ return $fields;
84
+
85
+ }, 10, 2 );
86
+ </pre>
87
+
88
+ ### How do I add additional fields to the social widget?
89
+
90
+ The social widget requires a different set of options but follows the same principle as above.
91
+
92
+ Here is an example:
93
+ <pre lang="php">
94
+ add_filter( 'wpcw_widget_social_custom_fields', function( $fields, $instance ) {
95
+
96
+ $fields['scribd'] = [
97
+ 'icon' => 'scribd', //See font-awesome icon slug
98
+ 'label' => __( 'Scribd', 'YOURTEXTDOMAIN' ),
99
+ 'default' => 'https://www.scribd.com/username',
100
+ 'select' => 'username',
101
+ 'sanitizer' => 'esc_url_raw',
102
+ 'escaper' => 'esc_url',
103
+ 'social' => true,
104
+ 'target' => '_blank',
105
+ ];
106
+
107
+ return $fields;
108
+
109
+ }, 10, 2 );
110
+ </pre>
111
+
112
+ == Changelog ==
113
+
114
+ = 1.3.3 - October 14, 2016 =
115
+
116
+ * Minor bug fixes
117
+ * Remove edit button when previewing in the customizer
118
+
119
+ = 1.3.2 - August 16, 2016 =
120
+
121
+ * WordPress 4.6 compatibility
122
+ * Fix bug with edit button not working
123
+ * Plugin icon update
124
+ * Update translation
125
+ * New: Add RSS to social networks.
126
+
127
+ Props [@jonathanbardo](https://github.com/jonathanbardo), [@fjarrett](https://github.com/fjarrett)
128
+
129
+ = 1.3.1 - June 3, 2016 =
130
+
131
+ * New: Language support for `mr`.
132
+ * New: Add 500px to social networks.
133
+
134
+ Props [@jonathanbardo](https://github.com/jonathanbardo), [@fjarrett](https://github.com/fjarrett), [@salvoventura](https://github.com/salvoventura)
135
+
136
+ = 1.3.0 - May 19, 2016 =
137
+
138
+ * New: Add front-end "Edit" link to quickly edit widgets in the Customizer.
139
+ * Fix: Use WP-CLI nightlies in tests.
140
+
141
+ Props [@jonathanbardo](https://github.com/jonathanbardo), [@fjarrett](https://github.com/fjarrett)
142
+
143
+ = 1.2.0 - April 12, 2016 =
144
+
145
+ * New: WordPress 4.5 compatibility.
146
+ * Tweak: Improve widget names.
147
+
148
+ Props [@jonathanbardo](https://github.com/jonathanbardo), [@fjarrett](https://github.com/fjarrett)
149
+
150
+ = 1.1.0 - March 15, 2016 =
151
+
152
+ * New: Support localization on Google Maps.
153
+
154
+ Props [@jonathanbardo](https://github.com/jonathanbardo), [@fjarrett](https://github.com/fjarrett)
155
+
156
+ = 1.0.4 - March 9, 2016 =
157
+
158
+ * Tweak: Language updates.
159
+
160
+ Props [@jonathanbardo](https://github.com/jonathanbardo)
161
+
162
+ = 1.0.2 - February 24, 2016 =
163
+
164
+ * New: Language support for 27 locales.
165
+
166
+ Props [@jonathanbardo](https://github.com/jonathanbardo)
167
+
168
+ = 1.0.1 - February 24, 2016 =
169
+
170
+ * New: Added possibility to add custom fields to contact and social widget.
171
+
172
+ Props [@jonathanbardo](https://github.com/jonathanbardo)
173
+
174
+ = 1.0.0 - February 23, 2016 =
175
+
176
+ * Initial release.
177
+
178
+ Props [@jonathanbardo](https://github.com/jonathanbardo), [@fjarrett](https://github.com/fjarrett)