<?php /*

 Composr
 Copyright (c) ocProducts, 2004-2016

 See text/EN/licence.txt for full licencing 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  ocProducts Ltd
 * @package    core
 */

/**
 * Automatically populate member geo CPFs as much as possible from other data.
 * Assumes Conversr.
 *
 * @param  ?MEMBER $member_id Member ID to do for (null: all)
 */
function autofill_geo_cpfs($member_id = null)
{
    $where = mixed();
    if (!is_null($member_id)) {
        $where['mf_member_id'] = $member_id;
    }

    $start = 0;
    $max = 100;
    do {
        $rows = $GLOBALS['FORUM_DB']->query_select('f_member_custom_fields f JOIN ' . $GLOBALS['FORUM_DB']->get_table_prefix() . 'f_members m ON m.id=f.mf_member_id', array('f.*', 'm.id', 'm_ip_address'), $where, 'ORDER BY mf_member_id', $max, $start);
        foreach ($rows as $row) {
            _autofill_geo_cpfs($row);
        }
        $start += $max;
    }
    while (array_key_exists(0, $rows));
}

/**
 * Automatically populate member geo CPFs (worker function).
 *
 * @param  array $row Member row
 *
 * @ignore
 */
function _autofill_geo_cpfs($row)
{
    require_code('cns_members');
    require_code('locations');
    require_code('locations_geocoding');

    $latitude_field = find_cms_cpf_field_id('cms_latitude');
    $longitude_field = find_cms_cpf_field_id('cms_longitude');

    $street_address_field = find_cms_cpf_field_id('cms_street_address');
    $city_field = find_cms_cpf_field_id('cms_city');
    $county_field = find_cms_cpf_field_id('cms_county');
    $state_field = find_cms_cpf_field_id('cms_state');
    $post_code_field = find_cms_cpf_field_id('cms_post_code');
    $country_field = find_cms_cpf_field_id('cms_country');

    $has_street_address = (!is_null($street_address_field)) && (!empty($row['field_' . strval($street_address_field)]));
    $has_city = (!is_null($city_field)) && (!empty($row['field_' . strval($city_field)]));
    $has_county = (!is_null($county_field)) && (!empty($row['field_' . strval($county_field)]));
    $has_state = (!is_null($state_field)) && (!empty($row['field_' . strval($state_field)]));
    $has_post_code = (!is_null($post_code_field)) && (!empty($row['field_' . strval($post_code_field)]));
    $has_country = (!is_null($country_field)) && (!empty($row['field_' . strval($country_field)]));
    $has_latitude = (!is_null($latitude_field)) && (!empty($row['field_' . strval($latitude_field)]));
    $has_longitude = (!is_null($longitude_field)) && (!empty($row['field_' . strval($longitude_field)]));

    $has_address = $has_city && $has_country;
    $has_gps = $has_latitude && $has_longitude;
    $has_ip = !empty($row['m_ip_address']);

    $changes = array();

    // GPS from address
    if ((!$has_latitude || !$has_longitude) && (isset($latitude_field)) && (isset($longitude_field))) {
        if ($has_address) {
            $address_components = array();
            if ($has_street_address) {
                $address_components[] = $row['field_' . strval($street_address_field)];
            }
            if ($has_city) {
                $address_components[] = $row['field_' . strval($city_field)];
            }
            if ($has_county) {
                $address_components[] = $row['field_' . strval($county_field)];
            }
            if ($has_state) {
                $address_components[] = $row['field_' . strval($state_field)];
            }
            if ($has_post_code) {
                $address_components[] = $row['field_' . strval($post_code_field)];
            }
            if ($has_country) {
                $address_components[] = $row['field_' . strval($country_field)];
            }

            $gps_parts = geocode(implode(', ', $address_components));
            if (!is_null($gps_parts)) {
                list($latitude, $longitude) = $gps_parts;
                if (($latitude_field !== null) && (!$has_latitude)) {
                    $changes['field_' . strval($latitude_field)] = $latitude;
                }
                if (($longitude_field !== null) && (!$has_longitude)) {
                    $changes['field_' . strval($longitude_field)] = $longitude;
                }
            }
        }
    }

    // Address from GPS (or IP)
    if (!$has_city || !$has_county || !$has_state || !$has_country) {
        if ($has_gps) {
            $_latitude = mixed();
            $_latitude = $row['field_' . strval($latitude_field)];
            if (is_float($_latitude)) {
                $latitude = $_latitude;
            } elseif ((is_string($_latitude)) && (is_numeric($_latitude))) {
                $latitude = floatval($_latitude);
            } else {
                $latitude = null;
            }

            $_longitude = mixed();
            $_longitude = $row['field_' . strval($longitude_field)];
            if (is_float($_longitude)) {
                $longitude = $_longitude;
            } elseif ((is_string($_longitude)) && (is_numeric($_longitude))) {
                $longitude = floatval($_longitude);
            } else {
                $longitude = null;
            }

            if (($latitude !== null) && ($longitude !== null)) {
                $address_parts = reverse_geocode($latitude, $longitude);
            } else {
                $address_parts = null;
            }
            if (!is_null($address_parts)) {
                list(, , $city, $county, $state, , $country) = $address_parts;
                if (($city_field !== null) && (!$has_city) && (!empty($city))) {
                    $changes['field_' . strval($city_field)] = $city;
                }
                if (($county_field !== null) && (!$has_county) && (!empty($county))) {
                    $changes['field_' . strval($county_field)] = $county;
                }
                if (($state_field !== null) && (!$has_state) && (!empty($state))) {
                    $changes['field_' . strval($state_field)] = $state;
                }
                if (($country_field !== null) && (!$has_country) && (!empty($country))) {
                    $changes['field_' . strval($country_field)] = $country;
                }
                // We cannot reliably geocode street addresses, so we don't go deeper than cities. We geocode *from* this to get GPS, but not vice-versa.
            }
        } elseif (($has_ip) && (!$has_country)) {
            $country = geolocate_ip($row['m_ip_address']);
            if (($country_field !== null) && (!empty($country))) {
                $changes['field_' . strval($country_field)] = $country;
            }
        }
    }

    // Save
    if (!empty($changes)) {
        $GLOBALS['FORUM_DB']->query_update('f_member_custom_fields', $changes, array('mf_member_id' => $row['mf_member_id']), '', 1);
    }
}
