/var/www/html/wp-content/plugins/koko-analytics/src/

OS : Linux

PHP Version : 7.4.33

Software : Apache/2.4.6 (CentOS) PHP/7.4.33

Information System :

', ''); ?>

urlencode($error_message)], $redirect_url); wp_safe_redirect($redirect_url); exit; } public function start_import(): void { // authorize user if (!current_user_can('manage_koko_analytics')) { return; } // verify nonce check_admin_referer('koko_analytics_start_jetpack_import'); // save params $params = [ 'wpcom-api-key' => trim($_POST['wpcom-api-key'] ?? ''), 'wpcom-blog-uri' => trim($_POST['wpcom-blog-uri'] ?? ''), 'date-start' => trim($_POST['date-start'] ?? ''), 'date-end' => trim($_POST['date-end'] ?? ''), ]; // all params are required if ($params['wpcom-api-key'] === '' || $params['wpcom-blog-uri'] === '' || $params['date-start'] === '' || $params['date-end'] === '') { $this->redirect_with_error(admin_url('/index.php?page=koko-analytics&tab=jetpack_importer'), __('A required field was missing', 'koko-analytics')); exit; } // first chunk is 30 days after date-start try { $date_start = new DateTimeImmutable($params['date-start']); $date_end = new DateTimeImmutable($params['date-end']); if ($date_end < $date_start) { throw new Exception("End date must be after start date"); } } catch (Exception $e) { $this->redirect_with_error(admin_url('/index.php?page=koko-analytics&tab=jetpack_importer'), __('Invalid date fields', 'koko-analytics')); exit; } // params are valid; let's go! update_option('koko_analytics_jetpack_import_params', $params, false); // work backwards from end date, so most recent stats first $chunk_end = $date_end; // determine size of each chunk to pull in and clamp it between 1 and supplied chunk size $max_chunk_size = isset($_GET['chunk-size']) ? (int) $_GET['chunk-size'] : 30; $chunk_size = \max(1, \min($max_chunk_size, $date_end->diff($date_start)->days)); // redirect to first chunk wp_safe_redirect(add_query_arg(['koko_analytics_action' => 'jetpack_import_chunk', 'chunk_size' => $chunk_size, 'chunk_end' => $chunk_end->format('Y-m-d'), '_wpnonce' => wp_create_nonce('koko_analytics_jetpack_import_chunk')])); exit; } public function import_chunk(): void { // authorize if (!current_user_can('manage_koko_analytics')) { return; } // verify nonce check_admin_referer('koko_analytics_jetpack_import_chunk'); // get params $params = get_option('koko_analytics_jetpack_import_params'); if (!$params) { $error_message = __('Missing parameters.', 'koko-analytics'); $this->redirect_with_error(admin_url('/index.php?page=koko-analytics&tab=jetpack_importer'), $error_message); exit; } $chunk_end = trim($_GET['chunk_end']); $chunk_size = (int) trim($_GET['chunk_size']); $date_start = new DateTimeImmutable($params['date-start']); $chunk_end = new DateTimeImmutable($chunk_end); // calculate next chunk end date and actual size of current chunk $next_chunk_end = $chunk_end->modify("-{$chunk_size} days"); if ($next_chunk_end < $date_start) { $chunk_size = max(1, $chunk_end->diff($date_start)->days); } // import this chunk try { $this->perform_chunk_import($params['wpcom-api-key'], $params['wpcom-blog-uri'], $chunk_end, $chunk_size); } catch (Exception $e) { // clean-up after ourselves delete_option('koko_analytics_jetpack_import_params'); // redirect to form page $this->redirect_with_error(admin_url('/index.php?page=koko-analytics&tab=jetpack_importer'), $e->getMessage()); exit; } // If we're done, redirect to success page if ($next_chunk_end < $date_start) { delete_option('koko_analytics_jetpack_import_params'); wp_safe_redirect(get_admin_url(null, '/index.php?page=koko-analytics&tab=jetpack_importer&success=1')); exit; } $url = add_query_arg(['koko_analytics_action' => 'jetpack_import_chunk', 'chunk_size' => $chunk_size, 'chunk_end' => $next_chunk_end->format('Y-m-d'), '_wpnonce' => wp_create_nonce('koko_analytics_jetpack_import_chunk')]); $chunk_start = $chunk_end->modify("-{$chunk_size} days"); $chunks_left = ceil($chunk_end->diff($date_start)->days / $chunk_size); // we could do a wp_safe_redirect() here // but instead we send some HTML to the client and perform a client-side redirect just so the user knows we're still alive and working ?>

' . $chunk_start->format('Y-m-d') . '', '' . $chunk_end->format('Y-m-d') . '' );?>

format('Y-m-d')); $url = "https://stats.wordpress.com/csv.php?api_key={$api_key}&blog_uri={$blog_uri}&end={$end}&table=postviews&format=json&days={$chunk_size}&limit=-1"; $response = wp_remote_post($url, [ 'timeout' => 90, ]); if ($response instanceof WP_Error) { $code = $response->get_error_code(); $message = $response->get_error_message(); throw new Exception(__('Error making remote request to the WordPress.com API:', 'koko-analytics') . " \n\n{$code} {$message}"); } $status_code = wp_remote_retrieve_response_code($response); if ($status_code >= 400) { $message = wp_remote_retrieve_response_message($response); $body = wp_remote_retrieve_body($response); throw new Exception(__('Received error response from WordPress.com API:', 'koko-analytics') . " \n\n{$status_code} {$message}\n\n{$body}"); } $body = wp_remote_retrieve_body($response); try { $data = json_decode($body, null, 512, JSON_THROW_ON_ERROR); } catch (Exception $e) { throw new Exception(__('Received non-JSON response from WordPress.com API:', 'koko-analytics') . "\n\n" . $body); } // API returns `null` for no data between two given dates // Let's turn it into an array instead if ($data === null) { $data = []; } // We now have an array of days in the following format: // [ [ "date" => "2020-10-31", "postviews" => [ [ "post_id" => 1, "views" => 2 ] ] ] ] /** @var wpdb $wpdb */ global $wpdb; foreach ($data as $item) { $site_views = 0; // if there were no stats for this date, simply skip if (count($item->postviews) === 0) { continue; } // update post stats for this date in a single bulk query $placeholders = rtrim(str_repeat('(%s,%d,%d,%d),', count($item->postviews)), ','); $values = []; foreach ($item->postviews as $postviews) { $site_views += $postviews->views; array_push($values, $item->date, $postviews->post_id, $postviews->views, $postviews->views); } $query = $wpdb->prepare("INSERT INTO {$wpdb->prefix}koko_analytics_post_stats(date, id, visitors, pageviews) VALUES {$placeholders} ON DUPLICATE KEY UPDATE visitors = visitors + VALUES(visitors), pageviews = pageviews + VALUES(pageviews)", $values); $wpdb->query($query); if ($wpdb->last_error !== '') { throw new Exception(__("A database error occurred: ", 'koko-analytics') . " {$wpdb->last_error}"); } // update site stats $query = $wpdb->prepare("INSERT INTO {$wpdb->prefix}koko_analytics_site_stats(date, visitors, pageviews) VALUES (%s, %d, %d) ON DUPLICATE KEY UPDATE visitors = visitors + VALUES(visitors), pageviews = pageviews + VALUES(pageviews)", [$item->date, $site_views, $site_views]); $wpdb->query($query); if ($wpdb->last_error !== '') { throw new Exception(__("A database error occurred: ", 'koko-analytics') . " {$wpdb->last_error}"); } } } }