<!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>