--- /dev/null
+<?php\r
+/*\r
+Plugin Name: danixland WPOrg Stats\r
+Plugin URI: https://danix.xyz/?p=3745\r
+Description: A simple plugin that shows useful stats about your plugins hosted on WordPress.org\r
+Version: 0.1\r
+Author: Danilo 'danix' Macri\r
+Author URI: https://danix.xyz\r
+Text Domain: dnxwporg\r
+\r
+This program is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
+*/\r
+\r
+\r
+/**\r
+ * Add plugin i18n domain: dnxwporg\r
+ * @since 0.1\r
+ */\r
+load_plugin_textdomain('dnxwporg', plugins_url() . '/danixland-wporg-stats/i18n/', 'danixland-wporg-stats/i18n/');\r
+\r
+/**\r
+ * Function that installs our widget options\r
+ * @since 0.1\r
+ */\r
+function dnxwporg_options_set() {\r
+ update_option( 'dnxwporg_author', 'danixland', '', 'yes' );\r
+ update_option( 'dnxwporg_plugins_stats', '', '', 'yes' );\r
+ update_option( 'dnxwporg_description', true, '', 'yes' );\r
+ update_option( 'dnxwporg_desc_content', '', '', 'yes' );\r
+ update_option( 'dnxwporg_linkto', true, '', 'yes' );\r
+ update_option( 'dnxwporg_use_icons', true, '', 'yes' );\r
+}\r
+\r
+/**\r
+ * Function that deletes our widget options\r
+ * @since 0.1\r
+ */\r
+function dnxwporg_options_unset() {\r
+ delete_option( 'dnxwporg_author' );\r
+ delete_option( 'dnxwporg_plugins_stats' );\r
+ delete_option( 'dnxwporg_description' );\r
+ delete_option( 'dnxwporg_desc_content' );\r
+ delete_option( 'dnxwporg_linkto' );\r
+ delete_option( 'dnxwporg_use_icons' );\r
+}\r
+\r
+/**\r
+ * Add function on plugin activation that'll set our plugin options\r
+ * @since 0.1\r
+ */\r
+register_activation_hook( __FILE__, 'dnxwporg_options_set' );\r
+\r
+/**\r
+ * Add function on plugin deactivation that'll unset our plugin options\r
+ * @since 0.3\r
+ */\r
+register_deactivation_hook( __FILE__, 'dnxwporg_options_unset' );\r
+\r
+function dnxwporg_load_js($hook) {\r
+ // Load only on ?page=widgets.php\r
+ if($hook != 'widgets.php') {\r
+ return;\r
+ }\r
+ wp_enqueue_script( 'dnxwporg-utils-js', plugins_url('js/dnxwporg-utils.js', __FILE__), array('jquery'), false, true );\r
+}\r
+add_action( 'admin_enqueue_scripts', 'dnxwporg_load_js' );\r
+\r
+\r
+/**\r
+ * Add function to retrieve the stats from api.wordpress.org\r
+ * @param $author - the plugin author nickname\r
+ * @return array - either the array with the info about the plugins or an empty array in case of failure\r
+ * @since 0.1\r
+ */\r
+function dnxwporg_get_plugins_stats( $author ) {\r
+ $url = 'https://api.wordpress.org/plugins/info/1.0/';\r
+ $fields = array(\r
+ 'downloaded' => true,\r
+ 'rating' => false,\r
+ 'description' => false,\r
+ 'short_description' => false,\r
+ 'donate_link' => false,\r
+ 'tags' => false,\r
+ 'sections' => false,\r
+ 'homepage' => true,\r
+ 'added' => false,\r
+ 'last_updated' => false,\r
+ 'compatibility' => false,\r
+ 'tested' => false,\r
+ 'requires' => false,\r
+ 'downloadlink' => false,\r
+ );\r
+ $args = (object) array( 'author' => $author, 'fields' => $fields );\r
+ $request = array( 'action' => 'query_plugins', 'timeout' => 15, 'request' => serialize( $args) );\r
+ $response = wp_remote_post( $url, array( 'body' => $request ) );\r
+ $plugins_info = unserialize( $response['body'] );\r
+ $result = array();\r
+ $total_dl = '';\r
+ $total_avg = '';\r
+ if ( isset( $plugins_info ) ) {\r
+ # let's build our array of data to return\r
+ foreach ($plugins_info->plugins as $plugin) {\r
+ $pl_name = $plugin->slug;\r
+ $pl_dirlink = 'https://wordpress.org/plugins/' . $pl_name;\r
+ $pl_icon = 'https://ps.w.org/' . $pl_name . '/assets/icon-256x256.png';\r
+ $pl_download = $plugin->download_link;\r
+ $pl_downloaded = $plugin->downloaded;\r
+ $pl_home = $plugin->homepage;\r
+ $pl_voters = $plugin->num_ratings;\r
+ $pl_stars = $plugin->ratings;\r
+ $avg_vote = ($pl_stars[1] + $pl_stars[2] * 2 + $pl_stars[3] * 3 + $pl_stars[4] * 4 + $pl_stars[5] * 5) / $pl_voters;\r
+ $pl_avg_vote = ( ! is_int($avg_vote) ? 0 : $avg_vote );\r
+ $total_dl += $pl_downloaded;\r
+ $total_avg += $pl_avg_vote;\r
+ $result[$pl_name] = array(\r
+ 'dir_link' => $pl_dirlink,\r
+ 'dl_link' => $pl_download,\r
+ 'home_link' => $pl_home,\r
+ 'icon' => $pl_icon,\r
+ 'downloaded' => $pl_downloaded,\r
+ 'voters' => $pl_voters,\r
+ 'avg_rating' => $pl_avg_vote\r
+ );\r
+ }\r
+ $avg = $total_avg / count($plugins_info->plugins);\r
+ $result['total_plugins'] = count($plugins_info->plugins);\r
+ $result['total_downloads'] = $total_dl;\r
+ $result['average_rating'] = round( $avg, 2);\r
+ return $result;\r
+ }\r
+ return array();\r
+}\r
+\r
+/**\r
+ * This function will execute with the scheduled cron job and update the data inside the option\r
+ * @since 0.1\r
+ */\r
+function dnxwporg_save_plugins_stats() {\r
+\r
+ $author = get_option('dnxwporg_author');\r
+ $plugins = dnxwporg_get_plugins_stats( $author );\r
+ update_option( 'dnxwporg_plugins_stats', $plugins );\r
+}\r
+add_action( 'dnxwporg_save_plugins_stats', 'dnxwporg_save_plugins_stats' );\r
+\r
+/**\r
+ * we schedule the cron if it's not yet scheduled\r
+ * @since 0.1\r
+ */\r
+if ( ! wp_next_scheduled( 'dnxwporg_save_plugins_stats' ) ) {\r
+ wp_schedule_event( 1407110400, 'daily', 'dnxwporg_save_plugins_stats' ); // 1407110400 is 08 / 4 / 2014 @ 0:0:0 UTC\r
+}\r
+\r
+/**\r
+ * Add function to widgets_init that'll load our widget.\r
+ * @since 0.1\r
+ */\r
+add_action( 'widgets_init', 'danixland_wporg_widget' );\r
+\r
+/**\r
+ * Register our widget.\r
+ * 'dnx_WPOrg' is the widget class used below.\r
+ *\r
+ * @since 0.1\r
+ */\r
+function danixland_wporg_widget() {\r
+ register_widget( 'dnx_WPOrg' );\r
+}\r
+\r
+/**\r
+ * dnx_WPOrg class.\r
+ * This class handles everything that needs to be handled with the widget:\r
+ * the settings, form, display, and update. Nice!\r
+ *\r
+ * @since 0.1\r
+ */\r
+class dnx_WPOrg extends WP_Widget {\r
+\r
+\r
+ /**\r
+ * Widget setup.\r
+ */\r
+ public function __construct() {\r
+ parent::__construct(\r
+ 'danixland-wporg-stats',\r
+ __( 'danixland WP.org Stats', 'dnxwporg' ),\r
+ array(\r
+ 'customize_selective_refresh' => true,\r
+ 'description' => __('Use this widget to display statistics about your WP.org hosted plugins on your site', 'dnxwporg'),\r
+ )\r
+ );\r
+ }\r
+\r
+ /**\r
+ * Displays the setup form for the widget in the widgets page\r
+ */\r
+ public function form( $instance ) {\r
+ $defaults = array( \r
+ 'title' => __( 'WP.org Plugins Stats', 'dnxwporg' ),\r
+ 'author' => get_option( 'dnxwporg_author' ),\r
+ 'description' => get_option( 'dnxwporg_description' ),\r
+ 'desc_content' => get_option( 'dnxwporg_desc_content' ),\r
+ 'link_wporg' => get_option( 'dnxwporg_linkto' ),\r
+ 'use_icons' => get_option( 'dnxwporg_use_icons' )\r
+ );\r
+ $instance = wp_parse_args( (array) $instance, $defaults );\r
+ extract( $instance, EXTR_SKIP );\r
+ ?>\r
+\r
+ <p>\r
+ <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e('Title:', 'dnxwporg'); ?></label>\r
+ <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
+ </p>\r
+ <p>\r
+ <label for="<?php echo $this->get_field_id( 'author' ); ?>"><?php _e('The username of the Plugin\'s author on WP.org', 'dnxwporg'); ?></label>\r
+ <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
+ </p>\r
+ <p>\r
+ <input class="checkbox" type="checkbox" <?php checked( $description, true ); ?> id="dnxwporg_use_desc" name="<?php echo $this->get_field_name( 'description' ); ?>" />\r
+ <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
+ <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
+ <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
+ </p>\r
+ <p>\r
+ <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
+ <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
+ </p>\r
+ <p>\r
+ <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
+ <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
+ </p>\r
+ <?php\r
+ }\r
+\r
+ /**\r
+ * Update the widget content\r
+ */\r
+ public function update( $new_instance, $old_instance ) {\r
+ $instance = $old_instance;\r
+\r
+ //Strip tags from title and name to remove HTML \r
+ $instance['title'] = sanitize_text_field( $new_instance['title'] );\r
+ $instance['author'] = strip_tags( $new_instance['author'] );\r
+ $instance['description'] = (bool) $new_instance['description'];\r
+ $instance['desc_content'] = sanitize_textarea_field( $new_instance['desc_content'] );\r
+ $instance['link_wporg'] = (bool) $new_instance['link_wporg'];\r
+ $instance['use_icons'] = (bool) $new_instance['use_icons'];\r
+\r
+ update_option( 'dnxwporg_author', $instance['author'] );\r
+ if ($old_instance['author'] !== $new_instance['author']) {\r
+ update_option( 'dnxwporg_plugins_stats', dnxwporg_get_plugins_stats( $instance['author'] ) );\r
+ }\r
+ update_option( 'dnxwporg_linkto', $instance['link_wporg'] );\r
+ update_option( 'dnxwporg_use_icons', $instance['use_icons'] );\r
+ update_option( 'dnxwporg_description', $instance['description'] );\r
+ update_option( 'dnxwporg_desc_content', $instance['desc_content'] );\r
+ \r
+ return $instance;\r
+ }\r
+\r
+ /**\r
+ * How to display the widget on the public side of the site.\r
+ */\r
+ public function widget( $args, $instance ) {\r
+ extract( $args );\r
+\r
+ /* Our variables from the widget settings. */\r
+ $title = apply_filters('widget_title', $instance['title'] );\r
+ $author = sanitize_user(get_option('dnxwporg_author'), true);\r
+ $description = get_option('dnxwporg_description');\r
+ $desc_content = get_option('dnxwporg_desc_content');\r
+ $linkto = get_option('dnxwporg_linkto');\r
+ $use_icons = get_option('dnxwporg_use_icons');\r
+\r
+ /* we recover the data from the option if it is set, otherwhise we call the retrieve function directly */\r
+ $option_stats = get_option('dnxwporg_plugins_stats');\r
+ $plugins = ( false === $option_stats ? dnxwporg_get_plugins_stats() : $option_stats );\r
+\r
+ /* Before widget (defined by themes). */\r
+ echo $before_widget;\r
+\r
+ /* Display the widget title if one was input (before and after defined by themes). */\r
+ if ( $title ) {\r
+ echo $before_title . $title . $after_title;\r
+ }\r
+\r
+ ?>\r
+ <div class="dnxwporg_container">\r
+ <?php if ($description) { ?>\r
+ <div class="dnxwporg_description">\r
+ <?php if (empty($desc_content)) : ?>\r
+ <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
+ <?php else : ?>\r
+ <p class="dnxwporg-pl-custom-desc"><?php echo $desc_content; ?></p>\r
+ <?php endif; ?>\r
+ </div>\r
+ <?php } ?>\r
+ <div class="dnxwporg_pl_list_container">\r
+ <ul class="dnxwporg_pl_list">\r
+ <?php foreach ($plugins as $name => $data) { \r
+ if (is_array($data) ) : ?>\r
+ <li class="dnxwporg_pl_item">\r
+ <a class="dnxwporg-pl-link" href="<?php echo ($linkto ? $data['dir_link'] : $data['home_link']) ?>">\r
+ <?php if ($use_icons) : ?>\r
+ <img class="dnxwporg-pl-link-icon" src="<?php echo $data['icon']; ?>" alt="<?php echo $name; ?>">\r
+ <?php endif; ?>\r
+ <span class="dnxwporg-pl-link-name"><?php echo $name; ?></span>\r
+ </a>\r
+ <p class="dnxwporg-pl-stats">\r
+ <span class="dnxwporg-pl-tot-dloads"><?php echo $data['downloaded']; ?></span>\r
+ <span class="dnxwporg-pl-avg-vote"><?php echo $data['avg_rating']; ?></span>\r
+ </p>\r
+ </li>\r
+ <?php endif;\r
+ } ?>\r
+ </ul>\r
+ </div>\r
+ </div>\r
+<?php\r
+ /* After widget (defined by themes). */\r
+ echo $after_widget;\r
+ }\r
+}\r
+\r
+?>\r
--- /dev/null
+=== danixland-wporg-stats ===
+Contributors: danixland
+Donate link: http://danix.xyz
+Tags: widget, sidebar, links, plugins, list
+Requires at least: 4.6
+Tested up to: 4.9.6
+Stable tag: 1.0
+
+This widget will display a list of plugins by the same author hosted on the WordPress.org plugins directory.
+
+== Description ==
+
+danixland-wporg.stats is a plugin that adds a new widget to be used on the Sidebar (or wherever you like).
+This widget will show a list of plugins by the same author, hosted on the WordPress Plugins directory. It uses the wordpress.org API to fetch all the details and it's able to show links to the plugin page on wordpress.org or to the URI specified by the author inside the plugin itself. Other stats displayed by the plugin are the total number of downloads for all the plugins and soon the plugin will be able to display even more stats.
+If an author has used the assets directory to store the plugin's icons, danixland-wporg-stats is able to fetch and display the icons as well.
+
+
+== Installation ==
+
+Installing danixland-wporg.stats is straightforward and requires just a few seconds:
+
+If you use the **"Add New Plugin"** pane from your dashboard just install it and activate it, then proceed to the last step and configure it.
+Otherwise follow these steps:
+
+1. Download the latest version of the plugin.
+1. If using the "Install Plugins->Upload" section on the WordPress admin area just upload the zip file, otherwise unpack the zip file and upload the **"danixland-wporg-stats"** directory inside the "wp-content/plugins" directory of your WordPress installation using your favourite ftp client.
+1. Activate the plugin through the 'Plugins' menu in WordPress.
+1. Add the widget to your sidebar from Appearance->Widgets.
+1. Configure the widget options through the panel which can be accessed from the Appearance->Widgets page.
+
+== Frequently Asked Questions ==
+
+= What can I do to customize even more the appearance of the widget? =
+
+The code generated by the plugin is wrapped in an HTML element with class `widget_danixland-wporg-stats`, what kind of element is decided by your theme, if unsure ask his creator. Inside this element you'll find the content of the widget wrapped inside a div with class `dnxwporg-container`.
+Contained in that element you'll find a div with the description and following there's a list of links for the plugins.
+
+Here's every single id and class used in this plugin:
+
+* `.widget_danixland-wporg-stats`
+* `.dnxwporg_container`
+* `.dnxwporg_description`
+* `.dnxwporg-pl-count`
+* `.dnxwporg-pl-dloads`
+* `.dnxwporg-pl-link-desc`
+
+= I'm stuck with your plugin and don't seem to be able to customize it/make it work, can you help me? =
+
+Of course, you can ask for help on [the forums](http://wordpress.org/support/) or write a comment on the main article for this plugin on [my site](https://danix.xyz/?p=3745), I'll reply ASAP ;)
+
+= I'd like this plugin to be translated in my language, can you do this for me? =
+
+This plugin ships with a .POT file that can be used to create a translation of the plugin in your language, so if you're familiar with english you can help by providing a translation and it will be added to future versions of the plugin along with a link to your site on these pages ;)
+
+To provide a translation simply edit the file "danixland-wporg.stats.pot" and fill every line with the traduction in your language, then save it as *yourlanguagecode.po* (E.G. it_IT.po for Italian), then contact me via the forums or my site and I'll tell you how to send this file to me. I'll add your translation ASAP.
+
+A number of softwares exists to help you with .po files, like [POEdit](http://sourceforge.net/projects/poedit/) or [Lokalize](http://userbase.kde.org/Lokalize "for kde users")
+
+####If you have any other questions feel free to ask
+
+== Screenshots ==
+
+1. The plugin widget as seen in the admin area.
+2. The widget with standard description as seen in the twentysixteen theme.
+3. The widget rocking a custom description.
+
+== Changelog ==
+
+= 1.0 =
+* This is the first version of the plugin.
+
+== Upgrade Notice ==
+
+= 1.0 =
+No upgrade since this is the first version ;)
+
+
+
+== ToDo list ==
+
+* I'll work on supporting themes as well.
+* custom tags inside the description
+* average download, average rating and more stats coming soon
+* I'm open to suggestions, so don't be shy.