- Timestamp:
- 12/14/2017 11:45:15 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/api.wordpress.org/public_html/events/1.0/index.php
r6260 r6275 15 15 * Short-circuit some requests if a traffic spike is larger than we can handle. 16 16 * 17 * THROTTLE_STICKY_WORDCAMPS prevents the additional `SELECT` query in `get_sticky_wordcamp()`. This is the 18 * least intrusive throttle for users, and should be tried first. 19 * 20 * If that doesn't help enough, then start throttling ip2location, since those happen automatically 21 * and are therefore less likely to be noticed by users. Throttling Geonames should be a last 22 * resort, since users will notice those the most, and will sometimes retry their requests, 23 * which makes the problem worse. 24 * 25 * THROTTLE_{ GEONAMES | IP2LOCATION } 17 26 * - A value of `0` means that 0% of requests will be throttled. 18 27 * - A value of `100` means that all cache-miss requests will be short-circuited with an error. … … 22 31 * In all of the above scenarios, requests that have cached results will always be served. 23 32 */ 33 define( 'THROTTLE_STICKY_WORDCAMPS', false ); 24 34 define( 'THROTTLE_GEONAMES', 0 ); 25 35 define( 'THROTTLE_IP2LOCATION', 0 ); 26 36 27 37 defined( 'DAY_IN_SECONDS' ) or define( 'DAY_IN_SECONDS', 60 * 60 * 24 ); 38 defined( 'WEEK_IN_SECONDS' ) or define( 'WEEK_IN_SECONDS', 7 * DAY_IN_SECONDS ); 28 39 29 40 // The test suite just needs the functions defined and doesn't want any headers or output … … 132 143 133 144 if ( $location ) { 134 $event_args = array(); 145 $event_args = array( 146 'is_client_core' => is_client_core( $_SERVER['HTTP_USER_AGENT'] ), 147 ); 135 148 136 149 if ( isset( $_REQUEST['number'] ) ) { … … 642 655 } 643 656 657 /** 658 * Get upcoming events for the requested location. 659 * 660 * @param array $args 661 * 662 * @return array 663 */ 644 664 function get_events( $args = array() ) { 645 665 global $wpdb, $cache_life, $cache_group; … … 651 671 $args['number'] = $args['number'] ?? 10; 652 672 $args['number'] = max( 0, min( $args['number'], 100 ) ); 673 674 // Distances in kilometers 675 $event_distances = array( 676 'meetup' => 100, 677 'wordcamp' => 400, 678 ); 653 679 654 680 $cache_key = 'events:' . md5( serialize( $args ) ); … … 665 691 // If we want nearby events, create a WHERE based on a bounded box of lat/long co-ordinates. 666 692 if ( !empty( $args['nearby'] ) ) { 667 // Distances in kilometers668 $event_distances = array(669 'meetup' => 100,670 'wordcamp' => 400,671 );672 693 $nearby_where = array(); 673 694 … … 696 717 // Just show upcoming events 697 718 $wheres[] = '`date_utc` >= %s'; 719 698 720 // Dates are in local-time not UTC, so the API output will contain events that have already happened in some parts of the world. 699 721 // TODO update this when the UTC dates are stored. … … 723 745 $sql_values 724 746 ) ); 747 748 if ( should_stick_wordcamp( $args, $raw_events ) ) { 749 $sticky_wordcamp = get_sticky_wordcamp( $args, $event_distances['wordcamp'] ); 750 751 if ( $sticky_wordcamp ) { 752 array_pop( $raw_events ); 753 array_push( $raw_events, $sticky_wordcamp ); 754 } 755 } 725 756 726 757 $events = array(); … … 743 774 744 775 wp_cache_set( $cache_key, $events, $cache_group, $cache_life ); 776 745 777 return $events; 778 } 779 780 /** 781 * Determine if conditions for sticking a WordCamp event to the response are met. 782 * 783 * @param array $request_args 784 * @param array $raw_events 785 * 786 * @return bool 787 */ 788 function should_stick_wordcamp( $request_args, $raw_events ) { 789 if ( THROTTLE_STICKY_WORDCAMPS ) { 790 return false; 791 } 792 793 // $raw_events already contains all the events that are coming up 794 if ( count( $raw_events ) < $request_args['number'] ) { 795 return false; 796 } 797 798 if ( ! $request_args['is_client_core'] ) { 799 return false; 800 } 801 802 $event_types = array_column( $raw_events, 'type' ); 803 804 if ( in_array( 'wordcamp', $event_types, true ) ) { 805 return false; 806 } 807 808 return true; 809 } 810 811 /** 812 * Get the WordCamp that should be stuck to the response. 813 * 814 * WordCamps are large, all-day (or multi-day) events that require more of attendees that meetups do. Attendees 815 * need to have more advanced notice of when they're occurring. In a city with an active meetup, the camp 816 * might not show up in the Events Widget until a week or two before it happens, which isn't enough time. 817 * 818 * @param array $request_args 819 * @param int $distance 820 * 821 * @return object|false A database row on success; `false` on failure. 822 */ 823 function get_sticky_wordcamp( $request_args, $distance ) { 824 global $wpdb; 825 826 $sticky_wordcamp_query = build_sticky_wordcamp_query( $request_args, $distance ); 827 $sticky_wordcamp = $wpdb->get_results( $wpdb->prepare( 828 $sticky_wordcamp_query['query'], 829 $sticky_wordcamp_query['values'] 830 ) ); 831 832 if ( ! empty( $sticky_wordcamp[0]->type ) ) { 833 return $sticky_wordcamp[0]; 834 } 835 836 return false; 837 } 838 839 /** 840 * Build the database query for fetching the WordCamp to stick to the response. 841 * 842 * @param array $request_args 843 * @param int $distance 844 * 845 * @return array 846 */ 847 function build_sticky_wordcamp_query( $request_args, $distance ) { 848 $where = $values = array(); 849 850 /* 851 * How far ahead the query should search for an upcoming camp. It should be high enough that attendees have 852 * enough time to prepare for the event, but low enough that it doesn't crowd out meetups that are happening 853 * in the mean-time, or make the content of the Events Widget feel less dynamic. Always having fresh content 854 * there is one of the things that makes the widget engaging. 855 */ 856 $date_upper_bound = 6 * WEEK_IN_SECONDS; 857 858 if ( ! empty( $request_args['nearby'] ) ) { 859 $bounded_box = get_bounded_coordinates( $request_args['nearby']['latitude'], $request_args['nearby']['longitude'], $distance ); 860 $where[] = '( `latitude` BETWEEN %f AND %f AND `longitude` BETWEEN %f AND %f )'; 861 $values[] = $bounded_box['latitude']['min']; 862 $values[] = $bounded_box['latitude']['max']; 863 $values[] = $bounded_box['longitude']['min']; 864 $values[] = $bounded_box['longitude']['max']; 865 } 866 867 // Allow queries for limiting to specific countries. 868 if ( ! empty( $request_args['country'] ) && preg_match( '![a-z]{2}!i', $request_args['country'] ) ) { 869 $where[] = '`country` = %s'; 870 $values[] = $request_args['country']; 871 } 872 873 $where = implode( ' AND ', $where ); 874 875 $query = " 876 SELECT 877 `type`, `title`, `url`, 878 `meetup`, `meetup_url`, 879 `date_utc`, `date_utc_offset`, 880 `location`, `country`, `latitude`, `longitude` 881 FROM `wporg_events` 882 WHERE 883 `type` = 'wordcamp' AND 884 $where AND 885 `date_utc` >= %s AND 886 `date_utc` <= %s 887 ORDER BY `date_utc` ASC 888 LIMIT 1" 889 ; 890 891 $values[] = gmdate( 'Y-m-d', time() - DAY_IN_SECONDS ); 892 $values[] = gmdate( 'Y-m-d', time() + $date_upper_bound ); 893 894 return compact( 'query', 'values' ); 746 895 } 747 896
Note: See TracChangeset
for help on using the changeset viewer.