1: <?php
  2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22: 
 23: 
 24: namespace Quform\Traduttore_Registry;
 25: 
 26: use DateTime;
 27: 
 28: const TRANSIENT_KEY_PLUGIN = 'traduttore-registry-plugins';
 29: const TRANSIENT_KEY_THEME  = 'traduttore-registry-themes';
 30: 
 31:  32:  33:  34:  35:  36:  37:  38:  39: 
 40: function add_project( $type, $slug, $api_url ) {
 41:     if ( ! has_action( 'init', __NAMESPACE__ . '\register_clean_translations_cache' ) ) {
 42:         add_action( 'init', __NAMESPACE__ . '\register_clean_translations_cache', 9999 );
 43:     }
 44: 
 45:      46:  47: 
 48:     add_filter(
 49:         'translations_api',
 50:         static function ( $result, $requested_type, $args ) use ( $type, $slug, $api_url ) {
 51:             if ( $type . 's' === $requested_type && $slug === $args['slug'] ) {
 52:                 return get_translations( $type, $args['slug'], $api_url );
 53:             }
 54: 
 55:             return $result;
 56:         },
 57:         10,
 58:         3
 59:     );
 60: 
 61:      62:  63:  64:  65: 
 66:     add_filter(
 67:         'site_transient_update_' . $type . 's',
 68:         static function ( $value ) use ( $type, $slug, $api_url ) {
 69:             if ( ! $value ) {
 70:                 $value = new \stdClass();
 71:             }
 72: 
 73:             if ( ! isset( $value->translations ) ) {
 74:                 $value->translations = [];
 75:             }
 76: 
 77:             $translations = get_translations( $type, $slug, $api_url );
 78: 
 79:             if ( ! isset( $translations['translations'] ) ) {
 80:                 return $value;
 81:             }
 82: 
 83:             $installed_translations = get_installed_translations( $type );
 84:             $locales                = get_available_locales();
 85: 
 86:             
 87:             $locales        = apply_filters( $type . 's_update_check_locales', $locales );
 88:             $active_locales = array_unique( $locales );
 89: 
 90:             foreach ( (array) $translations['translations'] as $translation ) {
 91:                 if ( ! \in_array( $translation['language'], $active_locales, true ) ) {
 92:                     continue;
 93:                 }
 94: 
 95:                 if ( $translation['updated'] && isset( $installed_translations[ $slug ][ $translation['language'] ] ) ) {
 96:                     $local  = sanitize_date( $installed_translations[ $slug ][ $translation['language'] ]['PO-Revision-Date'] );
 97:                     $remote = new DateTime( $translation['updated'] );
 98: 
 99:                     if ( $local >= $remote ) {
100:                         continue;
101:                     }
102:                 }
103: 
104:                 $translation['type'] = $type;
105:                 $translation['slug'] = $slug;
106: 
107:                 $value->translations[] = $translation;
108:             }
109: 
110:             return $value;
111:         }
112:     );
113: }
114: 
115: 116: 117: 118: 119: 
120: function register_clean_translations_cache() {
121:     $clear_plugin_translations = static function() {
122:         clean_translations_cache( 'plugin' );
123:     };
124:     $clear_theme_translations  = static function() {
125:         clean_translations_cache( 'theme' );
126:     };
127: 
128:     add_action( 'set_site_transient_update_plugins', $clear_plugin_translations );
129:     add_action( 'delete_site_transient_update_plugins', $clear_plugin_translations );
130: 
131:     add_action( 'set_site_transient_update_themes', $clear_theme_translations );
132:     add_action( 'delete_site_transient_update_themes', $clear_theme_translations );
133: }
134: 
135: 136: 137: 138: 139: 140: 141: 
142: function clean_translations_cache( $type ) {
143:     $transient_key = constant( __NAMESPACE__ . '\TRANSIENT_KEY_' . strtoupper( $type ) );
144:     $translations  = get_site_transient( $transient_key );
145: 
146:     if ( ! \is_object( $translations ) ) {
147:         return;
148:     }
149: 
150:     151: 152: 153: 
154:     $cache_lifespan   = 15;
155:     $time_not_changed = isset( $translations->_last_checked ) && ( time() - $translations->_last_checked ) > $cache_lifespan;
156: 
157:     if ( ! $time_not_changed ) {
158:         return;
159:     }
160: 
161:     delete_site_transient( $transient_key );
162: }
163: 
164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 
174: function get_translations( $type, $slug, $url ) {
175:     $transient_key = constant( __NAMESPACE__ . '\TRANSIENT_KEY_' . strtoupper( $type ) );
176:     $translations  = get_site_transient( $transient_key );
177: 
178:     if ( ! \is_object( $translations ) ) {
179:         $translations = new \stdClass();
180:     }
181: 
182:     if ( isset( $translations->{$slug} ) && \is_array( $translations->{$slug} ) ) {
183:         return $translations->{$slug};
184:     }
185: 
186:     $result = json_decode( wp_remote_retrieve_body( wp_remote_get( $url, [ 'timeout' => 2 ] ) ), true );
187:     if ( ! \is_array( $result ) ) {
188:         
189:         
190:         $result = [];
191:     }
192: 
193:     $translations->{$slug}       = $result;
194:     $translations->_last_checked = time();
195: 
196:     set_site_transient( $transient_key, $translations );
197: 
198:     return $result;
199: }
200: 
201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 
214: function sanitize_date( $date_string ) {
215:     $date_and_timezone = explode( '(', $date_string );
216:     $date_no_timezone  = trim( $date_and_timezone[0] );
217: 
218:     try {
219:         $date = new DateTime( $date_no_timezone );
220:     } catch ( \Exception $e ) {
221:         return new DateTime( '1970-01-01' );
222:     }
223: 
224:     return $date;
225: }
226: 
227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 
239: function get_installed_translations( $type ) {
240:     static $cache = [];
241: 
242:     if ( ! isset( $cache[ $type ] ) ) {
243:         $cache[ $type ] = wp_get_installed_translations( $type . 's' );
244:     }
245: 
246:     return $cache[ $type ];
247: }
248: 
249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 
260: function get_available_locales() {
261:     static $cache = null;
262: 
263:     if ( ! isset( $cache ) ) {
264:         $cache = array_values( get_available_languages() );
265:     }
266: 
267:     return $cache;
268: }
269: