<?php /*

 Composr
 Copyright (c) Christopher Graham, 2004-2024

 See docs/LICENSE.md for full licensing information.


 NOTE TO PROGRAMMERS:
   Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
   **** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****

*/

/**
 * @license    http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
 * @copyright  Christopher Graham
 * @package    search
 */

/**
 * Hook class.
 */
class Hook_admin_stats_searches extends CMSStatsProvider
{
    /**
     * Find metadata about stats graphs that are provided by this stats hook.
     *
     * @param  boolean $for_kpi Whether this is for setting up a KPI
     * @return ?array Map of metadata (null: hook is disabled)
     */
    public function info(bool $for_kpi = false) : ?array
    {
        if (!addon_installed('search')) {
            return null;
        }

        require_lang('search');

        return [
            'internal_searches' => [
                'label' => do_lang_tempcode('SEARCHES'),
                'category' => 'search_traffic',
                'filters' => [
                    'internal_searches__month_range' => new CMSStatsDateMonthRangeFilter('internal_searches__month_range', do_lang_tempcode('DATE_RANGE'), null, $for_kpi),
                    'internal_searches__term' => new CMSStatsTextFilter('internal_searches__term', do_lang_tempcode('SEARCH')),
                ],
                'pivot' => null,
            ],
            'internal_keywords' => [
                'label' => do_lang_tempcode('KEYWORDS'),
                'category' => 'search_traffic',
                'filters' => [
                    'internal_keywords__month_range' => new CMSStatsDateMonthRangeFilter('internal_keywords__month_range', do_lang_tempcode('DATE_RANGE'), null, $for_kpi),
                    'internal_searches__term' => new CMSStatsTextFilter('internal_searches__term', do_lang_tempcode('KEYWORD')),
                ],
                'pivot' => null,
            ],
        ];
    }

    /**
     * Preprocess raw data in the database into something we can efficiently draw graphs/conclusions from.
     *
     * @param  TIME $start_time Start timestamp
     * @param  TIME $end_time End timestamp
     * @param  array $data_buckets Map of data buckets; a map of bucket name to nested maps with the following maps in sequence: 'month', 'pivot', 'value' (then further map data) ; extended and returned by reference
     */
    public function preprocess_raw_data(int $start_time, int $end_time, array &$data_buckets)
    {
        require_code('temporal');

        $server_timezone = get_server_timezone();

        $max = 1000;
        $start = 0;

        require_code('content2');

        $query = 'SELECT s_primary,MIN(s_time) AS s_time FROM ' . get_table_prefix() . 'searches_logged WHERE ';
        $query .= 's_time>=' . strval($start_time) . ' AND ';
        $query .= 's_time<=' . strval($end_time);
        $query .= ' GROUP BY s_member_id,s_primary ORDER BY s_time';
        do {
            $rows = $GLOBALS['SITE_DB']->query($query, $max, $start);
            foreach ($rows as $row) {
                $timestamp = $row['s_time'];
                $timestamp = tz_time($timestamp, $server_timezone);

                $month = to_epoch_interval_index($timestamp, 'months');

                $search = cms_mb_strtolower($row['s_primary']);

                if (!isset($data_buckets['internal_searches'][$month][''][$search])) {
                    $data_buckets['internal_searches'][$month][''][$search] = 0;
                }
                $data_buckets['internal_searches'][$month][''][$search]++;

                list($_keywords) = _seo_meta_find_data([$search]);
                $keywords = explode(',', $_keywords);
                foreach ($keywords as $keyword) {
                    if (!isset($data_buckets['internal_keywords'][$month][''][$keyword])) {
                        $data_buckets['internal_keywords'][$month][''][$keyword] = 0;
                    }
                    $data_buckets['internal_keywords'][$month][''][$keyword]++;
                }
            }

            $start += $max;
        } while (!empty($rows));
    }

    /**
     * Generate final data from preprocessed data.
     *
     * @param  string $bucket Data bucket we want data for
     * @param  string $pivot Pivot value
     * @param  array $filters Map of filters (including pivot if applicable)
     * @return ?array Final data in standardised map format (null: could not generate)
     */
    public function generate_final_data(string $bucket, string $pivot, array $filters) : ?array
    {
        $range = $this->convert_month_range_filter_to_pair($filters[$bucket . '__month_range']);

        $data = [];

        $where = [
            'p_bucket' => $bucket,
            'p_pivot' => $pivot,
        ];
        $extra = '';
        $extra .= ' AND p_month>=' . strval($range[0]);
        $extra .= ' AND p_month<=' . strval($range[1]);
        $data_rows = $GLOBALS['SITE_DB']->query_select('stats_preprocessed', ['p_data'], $where, $extra);
        foreach ($data_rows as $data_row) {
            $_data = @unserialize($data_row['p_data']);
            foreach ($_data as $term => $num_searches) {
                if ((!empty($filters[$bucket . '__term'])) && (!simulated_wildcard_match($filters[$bucket . '__term'], $term, true))) {
                    continue;
                }

                if (!isset($data[$term])) {
                    $data[$term] = 0;
                }
                $data[$term] += $num_searches;
            }
        }

        if ($bucket == 'internal_searches') {
            return [
                'type' => self::GRAPH_BAR_CHART,
                'data' => $data,
                'x_axis_label' => do_lang_tempcode('SEARCH'),
                'y_axis_label' => do_lang_tempcode('COUNT_TOTAL'),
                'limit_bars' => true,
            ];
        }

        return [
            'type' => self::GRAPH_BAR_CHART,
            'data' => $data,
            'x_axis_label' => do_lang_tempcode('KEYWORD'),
            'y_axis_label' => do_lang_tempcode('COUNT_TOTAL'),
            'limit_bars' => true,
        ];
    }
}
