<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[3289] sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory: Plugin Directory: First swipe at handlers for api.wordpress.org/plugins/info/*.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://meta.trac.wordpress.org/changeset/3289">3289</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://meta.trac.wordpress.org/changeset/3289","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>dd32</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2016-06-02 06:55:49 +0000 (Thu, 02 Jun 2016)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Plugin Directory: First swipe at handlers for api.wordpress.org/plugins/info/*.
The API handlers are designed to be stand-alone scripts which run only with an object cache for caching, When cached data is unavailable, WordPress is included to fetch the data from a rest api endpoint.

See <a href="http://meta.trac.wordpress.org/ticket/1579">#1579</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryapiclassbasephp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/class-base.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryapiroutesclasspluginphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-plugin.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryclassplugindirectoryphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/class-plugin-directory.php</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryapiroutesclasspopularcategoriesphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-popular-categories.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryapiroutesclassquerypluginsphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-query-plugins.php</a></li>
<li>sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/</li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorystandaloneclasspluginsinfoapirequestphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/class-plugins-info-api-request.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorystandaloneclasspluginsinfoapiphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/class-plugins-info-api.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorystandalonedownloadsphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/downloads.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorystandalonepluginsinfoapiphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/plugins-info-api.php</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorydownloadhandlerphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/download-handler.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryapiclassbasephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/class-base.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/class-base.php      2016-06-01 22:00:11 UTC (rev 3288)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/class-base.php        2016-06-02 06:55:49 UTC (rev 3289)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -13,6 +13,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">        static function load_routes() {
</span><span class="cx" style="display: block; padding: 0 10px">                new Routes\Internal_Stats();
</span><span class="cx" style="display: block; padding: 0 10px">                new Routes\Plugin();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                new Routes\Popular_Categories();
+               new Routes\Query_Plugins();
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryapiroutesclasspluginphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-plugin.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-plugin.php     2016-06-01 22:00:11 UTC (rev 3288)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-plugin.php       2016-06-02 06:55:49 UTC (rev 3289)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3,6 +3,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> use WordPressdotorg\Plugin_Directory\Plugin_Directory;
</span><span class="cx" style="display: block; padding: 0 10px"> use WordPressdotorg\Plugin_Directory\Template;
</span><span class="cx" style="display: block; padding: 0 10px"> use WordPressdotorg\Plugin_Directory\API\Base;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+use WP_REST_Server;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * An API Endpoint to expose a single Plugin data via api.wordpress.org/plugins/info/1.x
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -13,7 +14,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        function __construct() {
</span><span class="cx" style="display: block; padding: 0 10px">                register_rest_route( 'plugins/v1', '/plugin/(?P<plugin_slug>[^/]+)/?', array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'methods'  => \WP_REST_Server::READABLE,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'methods'  => WP_REST_Server::READABLE,
</ins><span class="cx" style="display: block; padding: 0 10px">                         'callback' => array( $this, 'plugin_info' ),
</span><span class="cx" style="display: block; padding: 0 10px">                        'args' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                'plugin_slug' => array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30,14 +31,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return array A formatted array of all the data for the plugin.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        function plugin_info( $request ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                /*
-                * NOTE: Don't try to implement things such as the `fields` support in this endpoint.
-                *        It's highly unlikely we'll expose the REST API via api.wordpress.org as it is,
-                *        it'll probably have something in front of it.
-                *
-                * NOTE: Don't use any data from the client, such as the user_agent, just stick to what is presented in the GET payload.
-                *       It can't be cached if it's using data from other sources.
-                */
</del><span class="cx" style="display: block; padding: 0 10px">                 $plugin_slug = $request['plugin_slug'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                global $post;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -75,13 +68,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $result['author_profile'] = $this->get_user_profile_link( $post->post_author );
</span><span class="cx" style="display: block; padding: 0 10px">                $result['contributors'] = array();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                foreach ( (array)get_post_meta( $post_id, 'contributors', true ) as $contributor ) {
-                       $user = get_user_by( 'slug', $contributor );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $contributors = get_post_meta( $post_id, 'contributors', true ) ?: array( (int) $post->post_author );
+               foreach ( $contributors as $contributor ) {
+                       $user = is_int( $contributor ) ? get_user_by( 'id', $contributor ) : get_user_by( 'slug', $contributor );
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ( ! $user ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                continue;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $result['contributors'][ $contributor ] = array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $result['contributors'][ $user->user_nicename ] = array(
</ins><span class="cx" style="display: block; padding: 0 10px">                                 'profile' => $this->get_user_profile_link( $user ),
</span><span class="cx" style="display: block; padding: 0 10px">                                'avatar' => get_avatar_url( $user, array( 'default' => 'monsterid', 'rating' => 'g' ) ),
</span><span class="cx" style="display: block; padding: 0 10px">                                'display_name' => $user->display_name
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryapiroutesclasspopularcategoriesphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-popular-categories.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-popular-categories.php                         (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-popular-categories.php   2016-06-02 06:55:49 UTC (rev 3289)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,42 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordPressdotorg\Plugin_Directory\API\Routes;
+use WordPressdotorg\Plugin_Directory\API\Base;
+use WP_REST_Server;
+
+/**
+ * An API Endpoint to expose a the plugin categories data.
+ *
+ * @package WordPressdotorg_Plugin_Directory
+ */
+class Popular_Categories extends Base {
+
+       function __construct() {
+               register_rest_route( 'plugins/v1', '/popular-categories/?', array(
+                       'methods'  => WP_REST_Server::READABLE,
+                       'callback' => array( $this, 'popular_categories' ),
+               ) );
+       }
+
+       /**
+        * Endpoint to retrieve the popular categories for the plugin directory.
+        *
+        * @param \WP_REST_Request $request The Rest API Request.
+        * @return array A formatted array of all plugin categories on the site.
+        */
+       function popular_categories( $request ) {
+               $terms = get_terms( 'plugin_category', array( 'hide_empty' => false, 'orderby' => 'count', 'order' => 'DESC' ) );
+
+               $response = array();
+               foreach ( $terms as $term ) {
+                       $response[ $term->slug ] = array(
+                               'name'  => html_entity_decode( $term->name ),
+                               'slug'  => $term->slug,
+                               'count' => $term->count,
+                       );
+               }
+
+               return $response;
+       }
+
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-popular-categories.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryapiroutesclassquerypluginsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-query-plugins.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-query-plugins.php                              (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-query-plugins.php        2016-06-02 06:55:49 UTC (rev 3289)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,68 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordPressdotorg\Plugin_Directory\API\Routes;
+use WordPressdotorg\Plugin_Directory\API\Base;
+use WP_REST_Server;
+use WP_Query;
+
+/**
+ * An API Endpoint to Query plugins based on a select few query parameters.
+ *
+ * @package WordPressdotorg_Plugin_Directory
+ */
+class Query_Plugins extends Base {
+
+       protected $valid_query_fields = array(
+               'paged',
+               'posts_per_page',
+               'browse',
+               'favorites_user',
+               'plugin_category',
+               's',
+               'author_name'
+       );
+
+       function __construct() {
+               register_rest_route( 'plugins/v1', '/query-plugins/?', array(
+                       'methods'  => WP_REST_Server::READABLE,
+                       'callback' => array( $this, 'query' ),
+               ) );
+       }
+
+       /**
+        * Endpoint to query plugins.
+        *
+        * @param \WP_REST_Request $request The Rest API Request.
+        * @return array A formatted array of plugin results.
+        */
+       function query( $request ) {
+               $response = array(
+                       'info' => array(
+                               'page'    => 0,
+                               'pages'   => 0,
+                               'results' => 0,
+                       ),
+                       'plugins' => array(),
+               );
+
+               $query = array_intersect_key( $request->get_params(), array_flip( $this->valid_query_fields ) );
+
+               if ( ! $query ) {
+                       return $response;
+               }
+
+               $query['post_type'] = 'plugin';
+
+               $wp_query = new WP_Query( $query );
+
+               $response['info']['page']    = (int) $wp_query->get_query_var( 'paged' ) ?: 1;
+               $response['info']['pages']   = (int) $wp_query->max_num_pages            ?: 0;
+               $response['info']['results'] = (int) $wp_query->found_posts              ?: 0;
+
+               foreach ( $wp_query->posts as $post ) {
+                       $response['plugins'][] = $post->post_name;
+               }
+
+               return $response;
+       }
+
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-query-plugins.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryclassplugindirectoryphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/class-plugin-directory.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/class-plugin-directory.php      2016-06-01 22:00:11 UTC (rev 3288)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/class-plugin-directory.php        2016-06-02 06:55:49 UTC (rev 3289)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -372,7 +372,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                if ( 'plugin_built_for' == $term->taxonomy ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        return $this->package_link( false, $this->get_plugin_post( $term->slug ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // Term slug = Post Slug = /%postname%/
+                       return trailingslashit( home_url( $term->slug ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                return $termlink;
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorydownloadhandlerphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/download-handler.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/download-handler.php    2016-06-01 22:00:11 UTC (rev 3288)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/download-handler.php      2016-06-02 06:55:49 UTC (rev 3289)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,17 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordPressdotorg\Plugin_Directory;
-
-/*
- * This is a stand alone script, it operates with the expectation that the
- * global `$wpdb` is available and the object cache is configured.
- * 
- * Examples of URLs which are accepted:
- * - downloads.wordpress.org/plugin/hello-dolly.zip (trunk)
- * - downloads.wordpress.org/plugin/hello-dolly.latest-stable.zip
- * - downloads.wordpress.org/plugin/hello-dolly.3.2.1.zip
- */
-
-include __DIR__ . '/class-autoloader.php';
-Autoloader\register_class_path( __NAMESPACE__, __DIR__ );
-
-$serve = new Zip\Serve();
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorystandaloneclasspluginsinfoapirequestphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/class-plugins-info-api-request.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/class-plugins-info-api-request.php                           (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/class-plugins-info-api-request.php     2016-06-02 06:55:49 UTC (rev 3289)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,183 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordPressdotorg\Plugin_Directory\Standalone;
+
+/**
+ * Holds the information about the request payload, and massages it into a format we can use.
+ */
+class Plugins_Info_API_Request {
+       public $locale = 'en_US';
+       protected $args = array();
+       protected $requested_fields = array();
+
+       static $fields = array(
+               'active_installs'   => false,
+               'added'             => false,
+               'banners'           => false,
+               'compatibility'     => false,
+               'contributors'      => false,
+               'description'       => false,
+               'donate_link'       => false,
+               'downloaded'        => false,
+               'downloadlink'      => false,
+               'homepage'          => false,
+               'icons'             => false,
+               'last_updated'      => false,
+               'rating'            => false,
+               'ratings'           => false,
+               'reviews'           => false,
+               'requires'          => false,
+               'sections'          => false,
+               'short_description' => false,
+               'tags'              => false,
+               'tested'            => false,
+       );
+
+       static $plugins_info_fields_defaults = array(
+               'added'             => true,
+               'compatibility'     => true,
+               'contributors'      => true,
+               'downloaded'        => true,
+               'downloadlink'      => true,
+               'donate_link'       => true,
+               'homepage'          => true,
+               'last_updated'      => true,
+               'rating'            => true,
+               'ratings'           => true,
+               'requires'          => true,                         
+               'sections'          => true,
+               'tags'              => true,
+               'tested'            => true,         
+       );
+
+       static $query_plugins_fields_defaults = array(
+               'added'             => true,
+               'compatibility'     => true,
+               'downloaded'        => true,
+               'description'       => true,
+               'downloadlink'      => true,
+               'donate_link'       => true,
+               'homepage'          => true,
+               'last_updated'      => true,
+               'rating'            => true,
+               'ratings'           => true,
+               'requires'          => true,                         
+               'sections'          => true,
+               'short_description' => true,
+               'tags'              => true,
+               'tested'            => true, 
+       );
+
+       public function __construct( $args ) {
+               $args = (object) $args;
+
+               if ( !empty( $args->locale ) ) {
+                       $this->locale = $args->locale; // TODO: sanitize?
+               }
+               if ( !empty( $args->fields ) ) {
+                       $this->requested_fields = $this->parse_requested_fields( $args->fields );
+               }
+               unset( $args->locale, $args->fields );
+
+               $this->args = $args;
+       }
+
+       public function __get( $field ) {
+               if ( isset( $this->args->{$field} ) ) {
+                       return $this->args->{$field};
+               }
+               return null;
+       }
+
+       public function get_expected_fields( $method ) {
+               $fields = self::$fields;
+
+               if ( 'plugin_information' == $method ) {
+                       $fields = array_merge( $fields, self::$plugins_info_fields_defaults );
+               } elseif ( 'query_plugins' == $method ) {
+                       $fields = array_merge( $fields, self::$query_plugins_fields_defaults );
+               } else {
+                       return array();
+               }
+
+               // In WordPress 4.0+ we request the icons field however we don't use the
+               // description and compatibility fields so we exclue those by default unless requested.
+               if ( ! empty( $this->requested_fields['icons'] ) ) {
+                       $fields['compatibility'] = false;
+                       $fields['description']   = false;
+               }
+
+               // In WordPress x.y we start sending 'contributors' which means respond with a more detailed list of contributors.
+               if ( !isset( $this->requested_fields['contributors'] ) ) {
+                       $fields['bare_contributors'] = true;
+               }
+
+               $fields = array_merge( $fields, $this->requested_fields );
+
+               return $fields;
+       }
+
+       /**
+        * Sanitizes/parses the given fields parameter into a standard format. 
+        */
+       protected function parse_requested_fields( $fields ) {
+               $fields = is_string( $fields ) ? explode( ',', $fields ) : (array)$fields;
+
+               $requested_fields = array();
+               foreach ( $fields as $field => $include ) {
+                       if ( is_int( $field ) ) {
+                               $field = $include;
+                               $include = true;
+                               if ( '-' == substr( $field, 0, 1 ) ) {
+                                       $include = false;
+                                       $field = substr( $field, 1 );
+                               }
+                       }
+                       if ( isset( self::$fields[ $field ] ) ) {
+                               $requested_fields[ $field ] = (bool) $include;
+                       }
+               }
+
+               return $requested_fields;
+       }
+
+       /**
+        * Converts a request data object into the format expected by WP_Query & the WordPress wp-api rest endpoint.
+        */
+       public function query_plugins_params_for_query() {
+               $query = array();
+               // Paging
+               $query['paged']          = isset( $this->args->page )     ? $this->args->page     : 1;
+               $query['posts_per_page'] = isset( $this->args->per_page ) ? $this->args->per_page : 24;
+
+               // Views
+               if ( ! empty( $this->args->browse ) ) {
+                       $query['browse'] = $this->args->browse;
+
+               } elseif ( ! empty( $this->args->user ) ) {
+                       $query['browse'] = 'favorites';
+                       $query['favorites_user'] = $this->args->user;
+
+               } else {
+
+                       // Tags
+                       if ( ! empty( $this->args->tag ) ) {
+                               $query['plugin_category'] = is_array( $this->args->tag ) ? reset( $this->args->tag ) : $this->args->tag;
+                       }
+
+                       // Search
+                       if ( ! empty( $this->args->search ) ) {
+                               $query['s'] = $this->args->search;
+                       }
+
+                       // Author
+                       if ( ! empty( $this->args->author ) ) {
+                               $query['author_name'] = $this->args->author;
+                               //$query['contributor_search'] = $this->args->author; // TODO
+                       }
+
+               }
+
+               return $query;
+       }
+
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/class-plugins-info-api-request.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorystandaloneclasspluginsinfoapiphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/class-plugins-info-api.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/class-plugins-info-api.php                           (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/class-plugins-info-api.php     2016-06-02 06:55:49 UTC (rev 3289)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,367 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordPressdotorg\Plugin_Directory\Standalone;
+
+// The API caches here expire every 24~25hours, avoids cache races when multiple change at the same time.
+define( 'API_CACHE_EXPIRY', 24*60*60 + rand( 0, 60*60 ) );
+class Plugins_Info_API {
+
+       const CACHE_GROUP  = 'plugin_api_info';
+       const CACHE_EXPIRY = API_CACHE_EXPIRY;
+
+       protected $format = 'json';
+       protected $formats = array(
+               'jsonp' => 'application/javascript',
+               'json'  => 'application/json',
+               'php'   => 'text/plain',
+               'xml'   => 'application/xml',
+       );
+
+       function __construct( $format = 'json' ) {
+               if ( is_array( $format ) && 'jsonp' == $format[0] ) {
+                       $this->jsonp = $format[1];
+                       $format = 'json';
+               }
+               $this->format = $format;
+       }
+
+       /**
+        * Initiate the API and output the result.
+        *
+        * @param string $method  The method in the API to trigger.
+        * @param mixed  $request The request data/payload for the API handler.
+        */
+       public function handle_request( $method, $request ) {
+               $request = new Plugins_Info_API_Request( $request );
+               switch ( $method ) {
+                       case 'plugin_information':
+                               $this->plugin_information( $request );
+                               break;
+
+                       case 'query_plugins':
+                               $this->query_plugins( $request );
+                               break;
+
+                       case 'popular_categories':
+                       case 'hot_tags':
+                               $this->popular_categories( $request );
+                               break;
+
+                       default:
+                               if ( 'POST' != strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
+                                       die( '<p>Action not implemented. <a href="http://codex.wordpress.org/WordPress.org_API">API Docs</a>.</p>' );
+                               } else {
+                                       $this->output( (object) array(
+                                               'error' => 'Action not implemented'
+                                       ) );
+                               }
+                               break;
+               }
+       }
+
+       /**
+        * API Endpoint that handles the Plugin_Information route.
+        *
+        * @param Plugins_Info_API_Request $request    The Request object for this request.
+        * @param bool                     $return_raw Whether this is for another request (query_plugins) or an API request.
+        */
+       function plugin_information( $request, $return_raw = false ) {
+               if ( false === ( $response = wp_cache_get( $cache_key = $this->plugin_information_cache_key( $request ), self::CACHE_GROUP ) ) ) {
+                       $response = $this->internal_rest_api_call( 'plugins/v1/plugin/' . $request->slug, array( 'locale' => $request->locale ) );
+
+                       if ( 200 != $response->status ) {
+                               $response = array( 'error' => 'Plugin not found.' );
+                               wp_cache_set( $cache_key, $response, self::CACHE_GROUP, 60*60 ); // 1 hour TTL for 404's?
+                       } else {
+                               $response = $response->data;
+                               wp_cache_set( $cache_key, $response, self::CACHE_GROUP, self::CACHE_EXPIRY );
+                       }
+               }
+
+               if ( $return_raw ) {
+                       return $response;
+               }
+
+               // Only include the fields requested.
+               $response = $this->remove_unexpected_fields( $response, $request, 'plugin_information' );
+
+               $this->output( (object) $response );
+       }
+
+       /**
+        * Generates a Cache key for a plugin based on the request.
+        */
+       protected function plugin_information_cache_key( $request ) {
+               return 'plugin_information:' . $request->slug . ':' . ( $request->locale ?: 'en_US' );
+       }
+
+       /**
+        * Removes any extra fields which the API client doesn't need to be sent.
+        *
+        * @param array  $response The plugin_information response to remove fields from
+        * @param mixed  $request  The request object for the request.
+        * @param string $method   The requested method, used to determine the default fields to include.
+        *
+        * @return array The $resonse with the extra fields removed.
+        */
+       protected function remove_unexpected_fields( $response, $request, $method = '' ) {
+               $fields = $request->get_expected_fields( $method );
+               foreach ( $fields as $field => $include ) {
+                       if ( ! $include ) {
+                               unset( $response[ $field ] );
+                       }
+                       if ( 'reviews' === $field && ! $include ) {
+                               unset( $response['sections']['reviews'] );
+                       }
+               }
+
+               // Back-compatible routines.
+               // WordPress 4.x and older need a "bare" contributor map
+               if ( !empty( $fields['bare_contributors'] ) ) {
+                       $contribs = $response['contributors'];
+                       $response['contributors'] = array();
+                       foreach ( $contribs as $user => $data ) {
+                               $response['contributors'][ $user ] = $data['profile'];
+                       }
+               }
+
+               return $response;
+       }
+
+       /**
+        * API Endpoint to handle the 'query_plugins' action.
+        */
+       public function query_plugins( $request ) {
+               $response = array(
+                       'info' => array(
+                               'page' => 0,
+                               'pages' => 0,
+                               'results' => 0,
+                       ),
+                       'plugins' => array()
+               );
+
+               $cache_key = $this->query_plugins_cache_key( $request );
+
+               if ( false === ( $response = wp_cache_get( $cache_key, self::CACHE_GROUP ) ) ) {
+                       $response = $this->internal_rest_api_call( 'plugins/v1/query-plugins', $request->query_plugins_params_for_query() );
+                       if ( 200 != $response->status ) {
+                               $this->output( (object) array( 'error' => 'Query Failed.' ) );
+                               return;
+                       } else {
+                               $response = $response->data;
+                               wp_cache_set( $cache_key, $response, self::CACHE_GROUP, self::CACHE_EXPIRY );
+                       }
+               }
+
+               // Fill in the plugin details
+               foreach ( $response['plugins'] as $i => $plugin_slug ) {
+                       $response['plugins'][ $i ] = $this->plugin_information( new Plugins_API_Request( array( 'slug' => $plugin_slug, 'locale' => $request->locale ) ), true );
+               }
+
+               // Trim fields
+               foreach ( $response['plugins'] as $i => $plugin_data ) {
+                       $response['plugins'][$i] = $this->remove_unexpected_fields( $plugin_data, $request, 'query_plugins' );
+               }
+
+               $this->output( $response );
+       }
+
+       /**
+        * Generates a cache key for a given query_plugins request.
+        */
+       public function query_plugins_cache_key( $request ) {
+               return 'query_plugins:' . md5( serialize( $request->query_plugins_params_for_query() ) ) . ':' . ( $request->locale ?: 'en_US' );
+       }
+
+       /**
+        * API Endpoint for the 'populat_categories' and 'hot_tags' API endpoints.
+        */
+       public function popular_categories( $request ) {
+               if ( false === ( $response = false&& wp_cache_get( $cache_key = $this->popular_categories_cache_key( $request ), self::CACHE_GROUP ) ) ) {
+                       $response = $this->internal_rest_api_call( 'plugins/v1/popular-categories', array( 'locale' => $request->locale ) );
+
+                       if ( 200 != $response->status ) {
+                               $response = array( 'error' => 'Temporarily Unavailable' );
+                       } else {
+                               $response = $response->data;
+                               wp_cache_set( $cache_key, $response, self::CACHE_GROUP, self::CACHE_EXPIRY );
+                       }
+               }
+
+               if ( $request->number && count( $response ) > $request->number ) {
+                       $response = array_slice( $response, 0, $request->number, true );
+               }
+
+               $this->output( (object) $response );
+       }
+       /**
+        * Generates a cache key for a 'hot_categories' API request.
+        */
+       protected function popular_categories_cache_key( $request ) {
+               return 'hot_categories:' . $request->locale;
+       }
+
+       /**
+        * Output a given $response to the API client in the format specified by $this->format.
+        */
+       function output( $response ) {
+               header( 'Content-Type: ' . $this->formats[ $this->format ] );
+
+               switch ( $this->format ) {
+                       default:
+                       case 'json' :
+                       case 'jsonp' :
+                               $json = json_encode( $response );
+                               if ( 'jsonp' == $this->format ) {
+                                       echo "{$this->jsonp}($json)";
+                               } else {
+                                       echo $json;
+                               }
+                               break;
+       
+                       case 'php' :
+                               echo serialize( $response );
+                               break;
+       
+                       case 'xml' :
+                               echo '<' . '?xml version="1.0" encoding="utf-8"?' . ">\n";
+                               echo "<plugin>\n";
+                               $this->php_to_xml( $response );
+                               echo '</plugin>';
+                               break;
+               }
+
+               exit;
+       }
+
+       /**
+        * In the event that the Query needs to hit WordPress, this method can be used
+        * to load WordPress in the context of the correct site.
+        *
+        * Because "reasons" WordPress is told that it's a REST_REQUEST. remove it at
+        * your own risk.
+        */
+       public function load_wordpress() {
+               global $wpdb;
+               define( 'REST_REQUEST', true );
+
+               $host = $_SERVER['HTTP_HOST'];
+               $request_uri = $_SERVER['REQUEST_URI'];
+               $_SERVER['HTTP_HOST'] = 'wordpress.org';
+               $_SERVER['REQUEST_URI'] = '/plugins/';
+
+               require_once WPORGPATH . '/wp-load.php';
+
+               $_SERVER['HTTP_HOST'] = $host;
+               $_SERVER['REQUEST_URI'] = $request_uri;
+
+               return true;
+       }
+
+       /**
+        * Performs a 'GET' based REST API call without making a HTTP request.
+        */
+       public function internal_rest_api_call( $route, $query_params = array() ) {
+               if ( ! class_exists( '\WP_Rest_Request' ) ) {
+                       $this->load_wordpress();
+               }
+
+               $route = ltrim( $route, '/' );
+
+               $request = new \WP_REST_Request( 'GET', "/$route" );
+               if ( $query_params ) {
+                       $request->set_query_params( $query_params );
+               }
+
+               return rest_get_server()->dispatch( $request );
+       }
+
+       /**
+        * Outputs the result as XML.
+        *
+        * @param mixed $data The PHP structure to output as XML.
+        */
+       protected function php_to_xml( $data, $tabs = 0, $key = '' ) {
+               static $xml_tag = null;
+               if ( is_null( $xml_tag ) ) {
+                       $xml_tag = function( $tag, $type, $empty = false ) {
+                               static $NameStartChar = ':A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\x{2FF}\x{370}-\x{37D}\x{37F}-\x{1FFF}\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}';
+                               static $NameChar = '.0-9\xB7\x{0300}-\x{036F}\x{203F}-\x{2040}-';
+
+                               $start_right = $empty ? ' />' : '>';
+
+                               $tag = preg_replace( '/[^a-z0-9_.-]/i', '', $tag );
+
+                               if ( $tag && preg_match( "/^[$NameStartChar][{$NameStartChar}$NameChar]*\$/u", $tag ) ) {
+                                       return array( "<$tag type=\"$type\"$start_right", "</$tag>" );
+                               } elseif ( $tag ) {
+                                       return array( "<$type key=\"$tag\"$start_right", "</$type>" );
+                               }
+
+                               return array( "<$type$start_right", "</$type>" );
+                       };
+               }
+
+               echo str_repeat( "\t", $tabs );
+               switch ( $type = gettype( $data ) ) {
+                       case 'string' :
+                               $data = '<![CDATA[' . str_replace( ']]>', ']]]]><![CDATA[>', $data ) . ']]>';
+                       case 'boolean' :
+                       case 'integer' :
+                       case 'double' :
+                       case 'float' :
+                               list( $start, $close ) = $xml_tag( $key, $type, false );
+                               echo "$start$data$close";
+                               break;
+                       case 'NULL' :
+                               list( $start, $close ) = $xml_tag( $key, $type, true );
+                               echo $start;
+                               break;
+                       case 'array' :
+                               if ( empty( $data ) ) {
+                                       list( $start, $close ) = $xml_tag( $key, $type, true );
+                                       echo $start;
+                                       break;
+                               }
+
+                               list( $start, $close ) = $xml_tag( $key, $type, false );
+                               echo "$start\n";
+                               foreach ( $data as $k => $v ) {
+                                       $this->php_to_xml( $v, $tabs + 1, is_int( $k ) ? '' : $k );
+                               }
+                               echo str_repeat( "\t", $tabs );
+                               echo $close;
+                               break;
+                       case 'object' :
+                               if ( !$array = get_object_vars( $data ) ) {
+                                       if ( !$tabs ) {
+                                               break;
+                                       }
+
+                                       list( $start, $close ) = $xml_tag( $key, $type, true);
+                                       echo $start;
+                                       break;
+                               }
+
+                               list( $start, $close ) = $xml_tag( $key, $type, false );
+                               if ( $tabs ) {
+                                       echo $start;
+                               }
+                               foreach ( $array as $k => $v ) {
+                                       $this->php_to_xml( $v, $tabs + 1, $k );
+                               }
+                               echo str_repeat( "\t", $tabs );
+                               if ( $tabs ) {
+                                       echo $close;
+                               }
+                               break;
+                       case 'resource' :
+                       case 'unknown type' :
+                       default :
+                               break;
+               }
+               if ( $tabs ) {
+                       echo "\n";
+               }
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/class-plugins-info-api.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorystandalonedownloadsphpfromrev3288sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorydownloadhandlerphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/downloads.php (from rev 3288, sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/download-handler.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/downloads.php                                (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/downloads.php  2016-06-02 06:55:49 UTC (rev 3289)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,16 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordPressdotorg\Plugin_Directory;
+
+/*
+ * This is a stand alone script, it operates with the expectation that the
+ * global `$wpdb` is available and the object cache is configured.
+ * 
+ * Examples of URLs which are accepted:
+ * - downloads.wordpress.org/plugin/hello-dolly.zip (trunk)
+ * - downloads.wordpress.org/plugin/hello-dolly.latest-stable.zip
+ * - downloads.wordpress.org/plugin/hello-dolly.3.2.1.zip
+ */
+
+include dirname( __DIR__ ) . '/class-autoloader.php';
+Autoloader\register_class_path( __NAMESPACE__, dirname( __DIR__ ) );
+$serve = new Zip\Serve();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorystandalonepluginsinfoapiphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/plugins-info-api.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/plugins-info-api.php                         (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/plugins-info-api.php   2016-06-02 06:55:49 UTC (rev 3289)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,39 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordPressdotorg\Plugin_Directory;
+die();
+
+/**
+ * This is an example of how the /plugins/info/1.1/ endpoint may be implemented.
+ * It makes a lot of assumptions about the environment under which WordPress might be installed in.
+ */
+
+// Assume a standard wp-content/plugins/ plugin directory.
+define( 'WPORGPATH', dirname( dirname( dirname( dirname( __DIR__ ) ) ) ) . '/' );
+
+$_REQUEST = array(
+       'method' => 'plugin_information',
+       'request' => array(
+               'slug' => 'hello-dolly',
+               'fields' => 'active_installs',
+       )
+);
+
+$format  = 'json'; // json, jsonp, xml, or php
+$method  = $_REQUEST['method'];
+$request = $_REQUEST['request'];
+
+require __DIR__ . '/class-plugins-info-api.php';
+require __DIR__ . '/class-plugins-info-api-request.php';
+
+$api = new Plugins_Info_API( $format );
+
+if ( ! function_exists( 'wp_cache_init' ) ) {
+       // This script requires an object cache to be loaded
+       $api->load_wordpress();
+} else {
+       wp_cache_init();
+       // Logic for configuring the object cache here..
+}
+
+$api->handle_request( $method, $request );
+
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/standalone/plugins-info-api.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span></div>

</body>
</html>