FreeRetriever.php
221 lines
| 1 | <?php |
| 2 | |
| 3 | namespace SmashBalloon\Reviews\Common\Utils; |
| 4 | |
| 5 | use SmashBalloon\Reviews\Common\Builder\SBR_Sources; |
| 6 | use Smashballoon\Stubs\Services\ServiceProvider; |
| 7 | |
| 8 | /** |
| 9 | * Summary of FreeRetriever |
| 10 | */ |
| 11 | class FreeRetriever extends ServiceProvider |
| 12 | { |
| 13 | /** |
| 14 | * Free Sources/Reviews Retriever option name |
| 15 | * @var string |
| 16 | */ |
| 17 | public static $opt_name = 'sbr_free_retriever'; |
| 18 | |
| 19 | |
| 20 | /** |
| 21 | * Free Retriever Providers |
| 22 | * @var array |
| 23 | */ |
| 24 | public static $providers = ['google', 'yelp']; |
| 25 | |
| 26 | /** |
| 27 | * Transient flag that lets keyless Google/Yelp sources refetch within a |
| 28 | * short window even though they already fetched this week/ever. Set by |
| 29 | * SBR_Feed_Saver_Manager on an explicit "Clear All Caches" (which also |
| 30 | * resets the relay weekly window), so the immediate refresh can refetch |
| 31 | * instead of waiting up to 7 days. TTL-bounded (it is NOT consumed per |
| 32 | * call) — the relay's weekly window is the real cap and re-closes per |
| 33 | * source after the first fetch, which bounds the cost. |
| 34 | * |
| 35 | * Named with the `sbreviews_` prefix on purpose: clear_plugin_cache() purges |
| 36 | * `_transient_sbr_%`, and a `sbr_`-prefixed name would be swept immediately. |
| 37 | * |
| 38 | * @var string |
| 39 | */ |
| 40 | public const FORCE_REFETCH_FLAG = 'sbreviews_force_keyless_refetch'; |
| 41 | |
| 42 | /** |
| 43 | * Summary of api_keys |
| 44 | * @var array |
| 45 | */ |
| 46 | public $api_keys; |
| 47 | |
| 48 | /** |
| 49 | * Stored Google/Yelp Sources |
| 50 | * @var array |
| 51 | */ |
| 52 | public $sources; |
| 53 | |
| 54 | /** |
| 55 | * Settings |
| 56 | * @var array |
| 57 | */ |
| 58 | public $settings; |
| 59 | |
| 60 | /** |
| 61 | * Set Initial Values |
| 62 | */ |
| 63 | public function __construct() |
| 64 | { |
| 65 | $this->api_keys = get_option('sbr_apikeys', []); |
| 66 | $this->sources = SBR_Sources::sources_by_providers(self::$providers); |
| 67 | $this->settings = $this->get_settings(); |
| 68 | } |
| 69 | |
| 70 | /** |
| 71 | * Whether an explicit Clear All Caches has opened the keyless-refetch |
| 72 | * window. Honoured by limit_review_api_call() (Common + Pro) to bypass the |
| 73 | * already-fetched belt while the flag is set — the relay's weekly window is |
| 74 | * the real cap and is reset alongside the flag. Non-destructive: cached |
| 75 | * reviews stay put, so a failed refetch leaves the existing feed intact. |
| 76 | * |
| 77 | * @return bool |
| 78 | */ |
| 79 | protected static function should_force_refetch(): bool |
| 80 | { |
| 81 | return (bool) get_transient(self::FORCE_REFETCH_FLAG); |
| 82 | } |
| 83 | |
| 84 | /** |
| 85 | * Build settings for the App |
| 86 | * |
| 87 | * @return array |
| 88 | */ |
| 89 | public function get_settings() |
| 90 | { |
| 91 | $settings = [ |
| 92 | 'providers' => self::$providers, |
| 93 | 'providerInfo' => $this->check_possible_free_retrieving(), |
| 94 | 'emailVerification' => EmailVerification::get_email_verification_settings(), |
| 95 | 'isEmailVerified' => EmailVerification::check_verified() |
| 96 | ]; |
| 97 | |
| 98 | return $settings; |
| 99 | } |
| 100 | |
| 101 | |
| 102 | /** |
| 103 | * Check for Free API Retrieving |
| 104 | * |
| 105 | * @return array|boolean |
| 106 | */ |
| 107 | public function check_possible_free_retrieving() |
| 108 | { |
| 109 | $result = []; |
| 110 | foreach (self::$providers as $provider) { |
| 111 | //If API Key is empty |
| 112 | if (empty($this->api_keys[$provider])) { |
| 113 | $result[$provider] = [ |
| 114 | 'sourcesNumber' => $this->check_provider_souces_number($provider) |
| 115 | ]; |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | return $result; |
| 120 | } |
| 121 | |
| 122 | |
| 123 | /** |
| 124 | * Check for Free API Retrieving |
| 125 | * |
| 126 | * @return integer |
| 127 | */ |
| 128 | public function check_provider_souces_number($provider) |
| 129 | { |
| 130 | return empty($this->sources) |
| 131 | ? 0 |
| 132 | : count($this->filter_source_provider($provider)); |
| 133 | } |
| 134 | |
| 135 | /** |
| 136 | * Check for Free API Retrieving |
| 137 | * |
| 138 | * @return array |
| 139 | */ |
| 140 | public function filter_source_provider($provider) |
| 141 | { |
| 142 | return array_filter( |
| 143 | $this->sources, |
| 144 | function ($db_provider) use ($provider) { |
| 145 | return $db_provider['provider'] === $provider; |
| 146 | } |
| 147 | ); |
| 148 | } |
| 149 | |
| 150 | |
| 151 | /** |
| 152 | * Should Make API Call |
| 153 | * Return true in case we can make API Call |
| 154 | * Logic 1 : Current Provider has API Key |
| 155 | * Logic 2 : NO API Key + First time retrieving Reviews |
| 156 | * |
| 157 | * @return boolean |
| 158 | */ |
| 159 | public function check_api_call($provider, $provider_id) |
| 160 | { |
| 161 | //Return True if its Not Google/Yelp |
| 162 | if (!in_array($provider, self::$providers)) { |
| 163 | return true; |
| 164 | } |
| 165 | |
| 166 | //Return true Provider has API Key |
| 167 | if (!empty($this->api_keys[$provider])) { |
| 168 | return true; |
| 169 | } |
| 170 | $email_verified = EmailVerification::check_verified(); |
| 171 | //Email is Not Verified |
| 172 | if (!$email_verified) { |
| 173 | return false; |
| 174 | } |
| 175 | |
| 176 | |
| 177 | //Check only one update |
| 178 | $should_limit = $this->limit_review_api_call($provider, $provider_id); |
| 179 | return $should_limit === false; |
| 180 | } |
| 181 | |
| 182 | /** |
| 183 | * Should Make API Call |
| 184 | * |
| 185 | * @return boolean |
| 186 | */ |
| 187 | public function limit_review_api_call($provider, $provider_id) |
| 188 | { |
| 189 | $other_provider = $provider === 'google' |
| 190 | ? 'yelp' |
| 191 | : 'google'; |
| 192 | |
| 193 | $other_api_key = empty($this->settings['providerInfo'][$other_provider]); |
| 194 | |
| 195 | //Other Provider Sources Count |
| 196 | $other_sources = !empty($this->settings['providerInfo'][$other_provider]['sourcesNumber']) |
| 197 | ? $this->settings['providerInfo'][$other_provider]['sourcesNumber'] |
| 198 | : 0; |
| 199 | |
| 200 | //Means No API Key + Already Added Sources & Reviews in other Provider |
| 201 | $limit_other = !$other_api_key && $other_sources > 0; |
| 202 | if ($limit_other) { |
| 203 | return true; |
| 204 | } |
| 205 | |
| 206 | //Current Provider Sources Count |
| 207 | $current_sources = !empty($this->settings['providerInfo'][$provider]['sourcesNumber']) |
| 208 | ? $this->settings['providerInfo'][$provider]['sourcesNumber'] |
| 209 | : 0; |
| 210 | |
| 211 | //Reviews Already Fetched for this Source — but an explicit Clear All |
| 212 | //Caches opens a short refetch window (relay weekly window reset alongside). |
| 213 | $limit_current = SBR_Sources::already_fetched($provider, $provider_id); |
| 214 | if ($limit_current && ! self::should_force_refetch()) { |
| 215 | return true; |
| 216 | } |
| 217 | |
| 218 | return false; |
| 219 | } |
| 220 | } |
| 221 |