WordPress.org

Make WordPress Core

Ticket #27055: 27055.15.diff

File 27055.15.diff, 7.9 KB (added by matveb, 5 years ago)

Local cache for queries

  • wp-admin/js/theme.js

     
    213213                collection = _( collection.first( 20 ) );
    214214
    215215                return collection;
     216        },
     217
     218        // Handles requests for more themes
     219        // and caches results
     220        //
     221        // When we are missing a cache object we fire an apiCall()
     222        // which triggers events of `query:success` or `query:fail`
     223        query: function( request ) {
     224                /**
     225                 * @static
     226                 * @type Array
     227                 */
     228                var queries = this.queries,
     229                        self = this,
     230                        query;
     231
     232                // Search the query cache for matches.
     233                query = _.find( queries, function( query ) {
     234                        return _.isEqual( query.request, request );
     235                });
     236
     237                // Otherwise, send a new API call and add it to the cache.
     238                if ( ! query ) {
     239                        query = this.apiCall( request ).done( function( data ) {
     240                                // Update the collection with the queried data.
     241                                self.reset( data.themes );
     242
     243                                // Trigger a `query:success` event
     244                                // and a collection refresh event so the views are aware of changes.
     245                                self.trigger( 'query:success' );
     246                                self.trigger( 'update' );
     247
     248                                // Store the results and the query request
     249                                queries.push( { themes: data.themes, request: request } );
     250                        }).fail( function() {
     251                                self.trigger( 'query:fail' );
     252                        });
     253                } else {
     254                        // Only trigger an update event since we already have the themes
     255                        // on our cached object
     256                        this.reset( query.themes );
     257                        this.trigger( 'update' );
     258                }
     259        },
     260
     261        // Local cache array for API queries
     262        queries: [],
     263
     264        // Keep track of current query so we can handle pagination
     265        currentQuery: {
     266                apiPage: 1,
     267                request: {}
     268        },
     269
     270        // Send Ajax POST request to api.wordpress.org/themes
     271        apiCall: function( request ) {
     272                // Store current query request args
     273                // for later use with the event `theme:end`
     274                this.currentQuery.request = request;
     275
     276                // Ajax request to .org API
     277                return $.ajax({
     278                        url: 'https://api.wordpress.org/themes/info/1.1/?action=query_themes',
     279
     280                        // We want JSON data
     281                        dataType: 'json',
     282                        type: 'POST',
     283                        crossDomain: true,
     284
     285                        // Request data
     286                        data: {
     287                                action: 'query_themes',
     288                                request: _.extend({
     289                                        per_page: 36,
     290                                        // page: this.currentQuery.apiPage,
     291                                        fields: {
     292                                                description: true,
     293                                                tested: true,
     294                                                requires: true,
     295                                                rating: true,
     296                                                downloaded: true,
     297                                                downloadLink: true,
     298                                                last_updated: true,
     299                                                homepage: true,
     300                                                num_ratings: true
     301                                        }
     302                                }, request)
     303                        },
     304
     305                        beforeSend: function() {
     306                                // Spin it
     307                                $( 'body' ).addClass( 'loading-themes' );
     308                        }
     309                });
    216310        }
    217311});
    218312
     
    642736                self.instance = self.collection.paginate( page );
    643737
    644738                // If we have no more themes bail
    645                 if ( self.instance.length === 0 ) {
     739                if ( self.instance.size() === 0 ) {
     740                        // Fire a no-more-themes event.
     741                        this.parent.trigger( 'theme:end' );
    646742                        return;
    647743                }
    648744
     
    9911087                        request.tag = [ value.slice( 4 ) ];
    9921088                }
    9931089
    994                 // Send Ajax POST request to api.wordpress.org/themes
    995                 themes.view.Installer.prototype.apiCall( request ).done( function( data ) {
    996                                 // Update the collection with the queried data
    997                                 self.collection.reset( data.themes );
    998                                 // Trigger a collection refresh event to render the views
    999                                 self.collection.trigger( 'update' );
    1000 
    1001                                 // Un-spin it
    1002                                 $( 'body' ).removeClass( 'loading-themes' );
    1003                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1004                 }).fail( function() {
    1005                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1006                                 $( '.theme-browser' ).append( '<div class="error"><p>' + l10n.error + '</p></div>' );
    1007                 });
    1008 
    1009                 return false;
     1090                // Get the themes by sending Ajax POST request to api.wordpress.org/themes
     1091                // or searching the local cache
     1092                this.collection.query( request );
    10101093        }
    10111094});
    10121095
     
    10221105                'click [type="checkbox"]': 'addFilter'
    10231106        },
    10241107
    1025         // Send Ajax POST request to api.wordpress.org/themes
    1026         apiCall: function( request ) {
    1027                 return $.ajax({
    1028                         url: 'https://api.wordpress.org/themes/info/1.1/?action=query_themes',
    1029 
    1030                         // We want JSON data
    1031                         dataType: 'json',
    1032                         type: 'POST',
    1033                         crossDomain: true,
    1034 
    1035                         // Request data
    1036                         data: {
    1037                                 action: 'query_themes',
    1038                                 request: _.extend({
    1039                                         per_page: 36,
    1040                                         fields: {
    1041                                                 description: true,
    1042                                                 tested: true,
    1043                                                 requires: true,
    1044                                                 rating: true,
    1045                                                 downloaded: true,
    1046                                                 downloadLink: true,
    1047                                                 last_updated: true,
    1048                                                 homepage: true,
    1049                                                 num_ratings: true
    1050                                         }
    1051                                 }, request)
    1052                         },
    1053 
    1054                         beforeSend: function() {
    1055                                 // Spin it
    1056                                 $( 'body' ).addClass( 'loading-themes' );
    1057                         }
    1058                 });
    1059         },
    1060 
    10611108        // Handles all the rendering of the public theme directory
    10621109        browse: function( section ) {
    10631110                var self = this;
    10641111
    1065                 // @todo Cache the collection after fetching based on the section
    10661112                this.collection = new themes.Collection();
    10671113
    1068                 // Create a new collection with the proper theme data
    1069                 // for each section
    1070                 this.apiCall({ browse: section }).done( function( data ) {
    1071                         // Update the collection with the queried data
    1072                         self.collection.reset( data.themes );
    1073                         // Trigger a collection refresh event to render the views
    1074                         self.collection.trigger( 'update' );
     1114                // @work in progress
     1115                this.listenTo( this, 'theme:end', function() {
     1116                        self.collection.currentQuery.apiPage++;
     1117                });
    10751118
    1076                         // Un-spin it
     1119                this.listenTo( this.collection, 'update', function() {
     1120                        self.apiPage = 1;
     1121                });
     1122
     1123                this.listenTo( this.collection, 'query:success', function() {
    10771124                        $( 'body' ).removeClass( 'loading-themes' );
    10781125                        $( '.theme-browser' ).find( 'div.error' ).remove();
    10791126                });
    10801127
     1128                this.listenTo( this.collection, 'query:fail', function() {
     1129                        $( '.theme-browser' ).find( 'div.error' ).remove();
     1130                        $( '.theme-browser' ).append( '<div class="error"><p>' + l10n.error + '</p></div>' );
     1131                });
     1132
     1133                // Create a new collection with the proper theme data
     1134                // for each section
     1135                this.collection.query( { browse: section } );
     1136
    10811137                if ( this.view ) {
    10821138                        this.view.remove();
    10831139                }
     
    11531209
    11541210                // Construct the filter request
    11551211                // using the default values
    1156 
    1157                 // @todo Cache the collection after fetching based on the filter
    11581212                filter = _.union( filter, this.filtersChecked() );
    11591213                request = { tag: [ filter ] };
    11601214
    1161                 // Send Ajax POST request to api.wordpress.org/themes
    1162                 this.apiCall( request ).done( function( data ) {
    1163                                 // Update the collection with the queried data
    1164                                 self.collection.reset( data.themes );
    1165                                 // Trigger a collection refresh event to render the views
    1166                                 self.collection.trigger( 'update' );
    1167 
    1168                                 // Un-spin it
    1169                                 $( 'body' ).removeClass( 'loading-themes' );
    1170                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1171                 }).fail( function() {
    1172                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1173                                 $( '.theme-browser' ).append( '<div class="error"><p>' + l10n.error + '</p></div>' );
    1174                 });
    1175 
    1176                 return false;
     1215                // Get the themes by sending Ajax POST request to api.wordpress.org/themes
     1216                // or searching the local cache
     1217                this.collection.query( request );
    11771218        },
    11781219
    11791220        // Clicking on a checkbox triggers a tag request
     
    11821223                        tags = this.filtersChecked(),
    11831224                        request = { tag: tags };
    11841225
    1185                 // Send Ajax POST request to api.wordpress.org/themes
    1186                 this.apiCall( request ).done( function( data ) {
    1187                                 // Update the collection with the queried data
    1188                                 self.collection.reset( data.themes );
    1189                                 // Trigger a collection refresh event to render the views
    1190                                 self.collection.trigger( 'update' );
    1191 
    1192                                 // Un-spin it
    1193                                 $( 'body' ).removeClass( 'loading-themes' );
    1194                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1195                 }).fail( function() {
    1196                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1197                                 $( '.theme-browser' ).append( '<div class="error"><p>' + l10n.error + '</p></div>' );
    1198                 });
     1226                // Get the themes by sending Ajax POST request to api.wordpress.org/themes
     1227                // or searching the local cache
     1228                this.collection.query( request );
    11991229        },
    12001230
    12011231        // Get the checked filters and return an array