initial commit
[danixland-wporg-stats.git] / danixland-wporg-stats.php
CommitLineData
557c3817 1<?php\r
2/*\r
3Plugin Name: danixland WPOrg Stats\r
4Plugin URI: https://danix.xyz/?p=3745\r
5Description: A simple plugin that shows useful stats about your plugins hosted on WordPress.org\r
6Version: 0.1\r
7Author: Danilo 'danix' Macri\r
8Author URI: https://danix.xyz\r
9Text Domain: dnxwporg\r
10\r
11This program is distributed in the hope that it will be useful,\r
12but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
14*/\r
15\r
16\r
17/**\r
18 * Add plugin i18n domain: dnxwporg\r
19 * @since 0.1\r
20 */\r
21load_plugin_textdomain('dnxwporg', plugins_url() . '/danixland-wporg-stats/i18n/', 'danixland-wporg-stats/i18n/');\r
22\r
23/**\r
24 * Function that installs our widget options\r
25 * @since 0.1\r
26 */\r
27function dnxwporg_options_set() {\r
28 update_option( 'dnxwporg_author', 'danixland', '', 'yes' );\r
29 update_option( 'dnxwporg_plugins_stats', '', '', 'yes' );\r
30 update_option( 'dnxwporg_description', true, '', 'yes' );\r
31 update_option( 'dnxwporg_desc_content', '', '', 'yes' );\r
32 update_option( 'dnxwporg_linkto', true, '', 'yes' );\r
33 update_option( 'dnxwporg_use_icons', true, '', 'yes' );\r
34}\r
35\r
36/**\r
37 * Function that deletes our widget options\r
38 * @since 0.1\r
39 */\r
40function dnxwporg_options_unset() {\r
41 delete_option( 'dnxwporg_author' );\r
42 delete_option( 'dnxwporg_plugins_stats' );\r
43 delete_option( 'dnxwporg_description' );\r
44 delete_option( 'dnxwporg_desc_content' );\r
45 delete_option( 'dnxwporg_linkto' );\r
46 delete_option( 'dnxwporg_use_icons' );\r
47}\r
48\r
49/**\r
50 * Add function on plugin activation that'll set our plugin options\r
51 * @since 0.1\r
52 */\r
53register_activation_hook( __FILE__, 'dnxwporg_options_set' );\r
54\r
55/**\r
56 * Add function on plugin deactivation that'll unset our plugin options\r
57 * @since 0.3\r
58 */\r
59register_deactivation_hook( __FILE__, 'dnxwporg_options_unset' );\r
60\r
61function dnxwporg_load_js($hook) {\r
62 // Load only on ?page=widgets.php\r
63 if($hook != 'widgets.php') {\r
64 return;\r
65 }\r
66 wp_enqueue_script( 'dnxwporg-utils-js', plugins_url('js/dnxwporg-utils.js', __FILE__), array('jquery'), false, true );\r
67}\r
68add_action( 'admin_enqueue_scripts', 'dnxwporg_load_js' );\r
69\r
70\r
71/**\r
72 * Add function to retrieve the stats from api.wordpress.org\r
73 * @param $author - the plugin author nickname\r
74 * @return array - either the array with the info about the plugins or an empty array in case of failure\r
75 * @since 0.1\r
76 */\r
77function dnxwporg_get_plugins_stats( $author ) {\r
78 $url = 'https://api.wordpress.org/plugins/info/1.0/';\r
79 $fields = array(\r
80 'downloaded' => true,\r
81 'rating' => false,\r
82 'description' => false,\r
83 'short_description' => false,\r
84 'donate_link' => false,\r
85 'tags' => false,\r
86 'sections' => false,\r
87 'homepage' => true,\r
88 'added' => false,\r
89 'last_updated' => false,\r
90 'compatibility' => false,\r
91 'tested' => false,\r
92 'requires' => false,\r
93 'downloadlink' => false,\r
94 );\r
95 $args = (object) array( 'author' => $author, 'fields' => $fields );\r
96 $request = array( 'action' => 'query_plugins', 'timeout' => 15, 'request' => serialize( $args) );\r
97 $response = wp_remote_post( $url, array( 'body' => $request ) );\r
98 $plugins_info = unserialize( $response['body'] );\r
99 $result = array();\r
100 $total_dl = '';\r
101 $total_avg = '';\r
102 if ( isset( $plugins_info ) ) {\r
103 # let's build our array of data to return\r
104 foreach ($plugins_info->plugins as $plugin) {\r
105 $pl_name = $plugin->slug;\r
106 $pl_dirlink = 'https://wordpress.org/plugins/' . $pl_name;\r
107 $pl_icon = 'https://ps.w.org/' . $pl_name . '/assets/icon-256x256.png';\r
108 $pl_download = $plugin->download_link;\r
109 $pl_downloaded = $plugin->downloaded;\r
110 $pl_home = $plugin->homepage;\r
111 $pl_voters = $plugin->num_ratings;\r
112 $pl_stars = $plugin->ratings;\r
113 $avg_vote = ($pl_stars[1] + $pl_stars[2] * 2 + $pl_stars[3] * 3 + $pl_stars[4] * 4 + $pl_stars[5] * 5) / $pl_voters;\r
114 $pl_avg_vote = ( ! is_int($avg_vote) ? 0 : $avg_vote );\r
115 $total_dl += $pl_downloaded;\r
116 $total_avg += $pl_avg_vote;\r
117 $result[$pl_name] = array(\r
118 'dir_link' => $pl_dirlink,\r
119 'dl_link' => $pl_download,\r
120 'home_link' => $pl_home,\r
121 'icon' => $pl_icon,\r
122 'downloaded' => $pl_downloaded,\r
123 'voters' => $pl_voters,\r
124 'avg_rating' => $pl_avg_vote\r
125 );\r
126 }\r
127 $avg = $total_avg / count($plugins_info->plugins);\r
128 $result['total_plugins'] = count($plugins_info->plugins);\r
129 $result['total_downloads'] = $total_dl;\r
130 $result['average_rating'] = round( $avg, 2);\r
131 return $result;\r
132 }\r
133 return array();\r
134}\r
135\r
136/**\r
137 * This function will execute with the scheduled cron job and update the data inside the option\r
138 * @since 0.1\r
139 */\r
140function dnxwporg_save_plugins_stats() {\r
141\r
142 $author = get_option('dnxwporg_author');\r
143 $plugins = dnxwporg_get_plugins_stats( $author );\r
144 update_option( 'dnxwporg_plugins_stats', $plugins );\r
145}\r
146add_action( 'dnxwporg_save_plugins_stats', 'dnxwporg_save_plugins_stats' );\r
147\r
148/**\r
149 * we schedule the cron if it's not yet scheduled\r
150 * @since 0.1\r
151 */\r
152if ( ! wp_next_scheduled( 'dnxwporg_save_plugins_stats' ) ) {\r
153 wp_schedule_event( 1407110400, 'daily', 'dnxwporg_save_plugins_stats' ); // 1407110400 is 08 / 4 / 2014 @ 0:0:0 UTC\r
154}\r
155\r
156/**\r
157 * Add function to widgets_init that'll load our widget.\r
158 * @since 0.1\r
159 */\r
160add_action( 'widgets_init', 'danixland_wporg_widget' );\r
161\r
162/**\r
163 * Register our widget.\r
164 * 'dnx_WPOrg' is the widget class used below.\r
165 *\r
166 * @since 0.1\r
167 */\r
168function danixland_wporg_widget() {\r
169 register_widget( 'dnx_WPOrg' );\r
170}\r
171\r
172/**\r
173 * dnx_WPOrg class.\r
174 * This class handles everything that needs to be handled with the widget:\r
175 * the settings, form, display, and update. Nice!\r
176 *\r
177 * @since 0.1\r
178 */\r
179class dnx_WPOrg extends WP_Widget {\r
180\r
181\r
182 /**\r
183 * Widget setup.\r
184 */\r
185 public function __construct() {\r
186 parent::__construct(\r
187 'danixland-wporg-stats',\r
188 __( 'danixland WP.org Stats', 'dnxwporg' ),\r
189 array(\r
190 'customize_selective_refresh' => true,\r
191 'description' => __('Use this widget to display statistics about your WP.org hosted plugins on your site', 'dnxwporg'),\r
192 )\r
193 );\r
194 }\r
195\r
196 /**\r
197 * Displays the setup form for the widget in the widgets page\r
198 */\r
199 public function form( $instance ) {\r
200 $defaults = array( \r
201 'title' => __( 'WP.org Plugins Stats', 'dnxwporg' ),\r
202 'author' => get_option( 'dnxwporg_author' ),\r
203 'description' => get_option( 'dnxwporg_description' ),\r
204 'desc_content' => get_option( 'dnxwporg_desc_content' ),\r
205 'link_wporg' => get_option( 'dnxwporg_linkto' ),\r
206 'use_icons' => get_option( 'dnxwporg_use_icons' )\r
207 );\r
208 $instance = wp_parse_args( (array) $instance, $defaults );\r
209 extract( $instance, EXTR_SKIP );\r
210 ?>\r
211\r
212 <p>\r
213 <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e('Title:', 'dnxwporg'); ?></label>\r
214 <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $title; ?>" style="width:100%;" />\r
215 </p>\r
216 <p>\r
217 <label for="<?php echo $this->get_field_id( 'author' ); ?>"><?php _e('The username of the Plugin\'s author on WP.org', 'dnxwporg'); ?></label>\r
218 <input type="text" class="widefat" id="<?php echo $this->get_field_id( 'author' ); ?>" name="<?php echo $this->get_field_name( 'author' ); ?>" value="<?php echo $author ?>" style="width:100%;" />\r
219 </p>\r
220 <p>\r
221 <input class="checkbox" type="checkbox" <?php checked( $description, true ); ?> id="dnxwporg_use_desc" name="<?php echo $this->get_field_name( 'description' ); ?>" />\r
222 <label for="<?php echo $this->get_field_id( 'description' ); ?>"><?php _e('Select this if you want to display a small description inside the widget.', 'dnxwporg'); ?></label>\r
223 <textarea id="dnxwporg_custom_desc" name="<?php echo $this->get_field_name( 'desc_content' ); ?>" rows="10" cols="30" <?php disabled( $description, false ); ?> /><?php echo $desc_content; ?></textarea>\r
224 <label for="<?php echo $this->get_field_id( 'desc_content' ); ?>"><?php _e('If active but empty, the standard plugin description will be used.', 'dnxwporg'); ?></label>\r
225 </p>\r
226 <p>\r
227 <input class="checkbox" type="checkbox" <?php checked( $link_wporg, true ); ?> id="<?php echo $this->get_field_id( 'link_wporg' ); ?>" name="<?php echo $this->get_field_name( 'link_wporg' ); ?>" />\r
228 <label for="<?php echo $this->get_field_id( 'link_wporg' ); ?>"><?php _e('If selected, your links will point to the WP.org plugin page, if not, the PLUGIN URI will be used instead.', 'dnxwporg'); ?></label>\r
229 </p>\r
230 <p>\r
231 <input class="checkbox" type="checkbox" <?php checked( $use_icons, true ); ?> id="<?php echo $this->get_field_id( 'use_icons' ); ?>" name="<?php echo $this->get_field_name( 'use_icons' ); ?>" />\r
232 <label for="<?php echo $this->get_field_id( 'use_icons' ); ?>"><?php _e('If selected, the widget will display the icon from the assets directory in your plugin svn folder.', 'dnxwporg'); ?></label>\r
233 </p>\r
234 <?php\r
235 }\r
236\r
237 /**\r
238 * Update the widget content\r
239 */\r
240 public function update( $new_instance, $old_instance ) {\r
241 $instance = $old_instance;\r
242\r
243 //Strip tags from title and name to remove HTML \r
244 $instance['title'] = sanitize_text_field( $new_instance['title'] );\r
245 $instance['author'] = strip_tags( $new_instance['author'] );\r
246 $instance['description'] = (bool) $new_instance['description'];\r
247 $instance['desc_content'] = sanitize_textarea_field( $new_instance['desc_content'] );\r
248 $instance['link_wporg'] = (bool) $new_instance['link_wporg'];\r
249 $instance['use_icons'] = (bool) $new_instance['use_icons'];\r
250\r
251 update_option( 'dnxwporg_author', $instance['author'] );\r
252 if ($old_instance['author'] !== $new_instance['author']) {\r
253 update_option( 'dnxwporg_plugins_stats', dnxwporg_get_plugins_stats( $instance['author'] ) );\r
254 }\r
255 update_option( 'dnxwporg_linkto', $instance['link_wporg'] );\r
256 update_option( 'dnxwporg_use_icons', $instance['use_icons'] );\r
257 update_option( 'dnxwporg_description', $instance['description'] );\r
258 update_option( 'dnxwporg_desc_content', $instance['desc_content'] );\r
259 \r
260 return $instance;\r
261 }\r
262\r
263 /**\r
264 * How to display the widget on the public side of the site.\r
265 */\r
266 public function widget( $args, $instance ) {\r
267 extract( $args );\r
268\r
269 /* Our variables from the widget settings. */\r
270 $title = apply_filters('widget_title', $instance['title'] );\r
271 $author = sanitize_user(get_option('dnxwporg_author'), true);\r
272 $description = get_option('dnxwporg_description');\r
273 $desc_content = get_option('dnxwporg_desc_content');\r
274 $linkto = get_option('dnxwporg_linkto');\r
275 $use_icons = get_option('dnxwporg_use_icons');\r
276\r
277 /* we recover the data from the option if it is set, otherwhise we call the retrieve function directly */\r
278 $option_stats = get_option('dnxwporg_plugins_stats');\r
279 $plugins = ( false === $option_stats ? dnxwporg_get_plugins_stats() : $option_stats );\r
280\r
281 /* Before widget (defined by themes). */\r
282 echo $before_widget;\r
283\r
284 /* Display the widget title if one was input (before and after defined by themes). */\r
285 if ( $title ) {\r
286 echo $before_title . $title . $after_title;\r
287 }\r
288\r
289 ?>\r
290 <div class="dnxwporg_container">\r
291 <?php if ($description) { ?>\r
292 <div class="dnxwporg_description">\r
293 <?php if (empty($desc_content)) : ?>\r
294 <p class="dnxwporg-pl-standard-desc"><?php printf( _n('%s contributed <span class="dnxwporg-pl-count">%s</span> plugin with <span class="dnxwporg-pl-dloads">%s</span> total downloads and an average rating of <span class="dnxwporg-pl-avg-rating">%s</span>', '%s contributed <span class="dnxwporg-pl-count">%s</span> plugins with <span class="dnxwporg-pl-dloads">%s</span> total downloads and an average rating of <span class="dnxwporg-pl-avg-rating">%s</span>', $plugins['total_plugins'], 'dnxwporg' ), $author, $plugins['total_plugins'], $plugins['total_downloads'], $plugins['average_rating'] ); ?></p>\r
295 <?php else : ?>\r
296 <p class="dnxwporg-pl-custom-desc"><?php echo $desc_content; ?></p>\r
297 <?php endif; ?>\r
298 </div>\r
299 <?php } ?>\r
300 <div class="dnxwporg_pl_list_container">\r
301 <ul class="dnxwporg_pl_list">\r
302 <?php foreach ($plugins as $name => $data) { \r
303 if (is_array($data) ) : ?>\r
304 <li class="dnxwporg_pl_item">\r
305 <a class="dnxwporg-pl-link" href="<?php echo ($linkto ? $data['dir_link'] : $data['home_link']) ?>">\r
306 <?php if ($use_icons) : ?>\r
307 <img class="dnxwporg-pl-link-icon" src="<?php echo $data['icon']; ?>" alt="<?php echo $name; ?>">\r
308 <?php endif; ?>\r
309 <span class="dnxwporg-pl-link-name"><?php echo $name; ?></span>\r
310 </a>\r
311 <p class="dnxwporg-pl-stats">\r
312 <span class="dnxwporg-pl-tot-dloads"><?php echo $data['downloaded']; ?></span>\r
313 <span class="dnxwporg-pl-avg-vote"><?php echo $data['avg_rating']; ?></span>\r
314 </p>\r
315 </li>\r
316 <?php endif;\r
317 } ?>\r
318 </ul>\r
319 </div>\r
320 </div>\r
321<?php\r
322 /* After widget (defined by themes). */\r
323 echo $after_widget;\r
324 }\r
325}\r
326\r
327?>\r