<?php
/*
Plugin Name: GeoReg
Plugin URI: http://marketplace.appthemes.com/plugins/georeg/
Description: A plugin that transparently captures detailed geographic information when a new user registers.

AppThemes ID: georeg

Version: 1.1
Author: appthemes
Author URI: http://www.appthemes.com
Text Domain: georeg
*/



class AT_GeoReg {

	/**
	 * Setups plugin.
	 *
	 * @return void
	 */
	public function __construct() {
		add_action( 'init',                           array( &$this, 'load_plugin_textdomain' ) );
		add_action( 'login_form_register',            array( &$this, 'add_enqueue_scripts' ) );
		add_action( 'signup_header',                  array( &$this, 'add_enqueue_scripts' ) ); // multisite
		add_action( 'bp_head',                        array( &$this, 'add_enqueue_scripts' ) ); // buddypress
		add_action( 'register_form',                  array( &$this, 'add_geo_fields' ) );
		add_action( 'signup_hidden_fields',           array( &$this, 'add_geo_fields' ) ); // multisite
		add_action( 'bp_after_signup_profile_fields', array( &$this, 'add_geo_fields' ) ); // buddypress
		add_action( 'user_register',                  array( &$this, 'save_geo_fields' ) );
		add_action( 'wpmu_new_user',                  array( &$this, 'save_geo_fields' ) ); // multisite
		add_filter( 'add_signup_meta',                array( &$this, 'save_geo_fields_ms' ) ); // multisite
		add_filter( 'bp_core_signup_user',            array( &$this, 'save_geo_fields_bp', 10, 5 ) ); // buddypress
		add_action( 'wpmu_activate_user',             array( &$this, 'move_geo_fields_ms' ), 10, 3 ); // multisite - only triggered when plugin is network activated!!!
		add_action( 'edit_user_profile',              array( &$this, 'show_geo_fields' ) );
		add_filter( 'manage_users_columns',           array( &$this, 'add_user_columns' ) );
		add_filter( 'manage_users_custom_column',     array( &$this, 'add_user_column_value' ), 10, 3 );
		add_action( 'edit_user_profile_update',       array( &$this, 'save_geo_fields' ) );
	}


	/**
	 * Loads plugin textdomain.
	 *
	 * @return void
	 */
	public function load_plugin_textdomain() {
		load_plugin_textdomain( 'georeg', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
	}


	/**
	 * Returns language code for use in google map.
	 *
	 * @return void
	 */
	public function wplang() {
		$a = explode( '_', get_locale() );

		return $a[0];
	}


	/**
	 * Enqueues scripts.
	 * Registration page doesn't natively enqueue jQuery.
	 *
	 * @return void
	 */
	public function add_enqueue_scripts() {
		wp_enqueue_script( 'jquery' );
	}


	/**
	 * Returns an array of all geo fields.
	 *
	 * @return array
	 */
	public function geo_fields() {
		$fields = array(
			'geoip_ip_address'    =>  __( 'IP Address', 'georeg' ),
			'geoip_country_code'  =>  __( 'Country Code', 'georeg' ),
			'geoip_country_name'  =>  __( 'Country Name', 'georeg' ),
			'geoip_region'        =>  __( 'Region', 'georeg' ),
			'geoip_region_name'   =>  __( 'Region Name', 'georeg' ),
			'geoip_city'          =>  __( 'City', 'georeg' ),
			'geoip_postal_code'   =>  __( 'Postal Code', 'georeg' ),
			'geoip_latitude'      =>  __( 'Latitude', 'georeg' ),
			'geoip_longitude'     =>  __( 'Longitude', 'georeg' ),
		);

		return apply_filters( 'geo_fields', $fields );
	}


	/**
	 * Returns an array of all geo field keys mapped to used service.
	 *
	 * @return array
	 */
	public function geo_fields_map() {
		$fields = array();

		// default Telize fields map
		$fields_map = array(
			'geoip_ip_address'   => 'ip',
			'geoip_country_code' => 'country_code',
			'geoip_country_name' => 'country',
			'geoip_region'       => 'region_code',
			'geoip_region_name'  => 'region',
			'geoip_city'         => 'city',
			'geoip_postal_code'  => 'postal_code',
			'geoip_latitude'     => 'latitude',
			'geoip_longitude'    => 'longitude',
		);
		$fields_map = apply_filters( 'geo_fields_map', $fields_map );

		// return only fields that have relation
		foreach ( $this->geo_fields() as $key => $name ) {
			if ( isset( $fields_map[ $key ] ) ) {
				$fields[ $key ] = $fields_map[ $key ];
			}
		}

		return $fields;
	}


	/**
	 * Returns geoip service url.
	 *
	 * @return string
	 */
	public function get_service_url() {
		$service_url = 'http://www.telize.com/geoip';

		return apply_filters( 'geo_service_url', $service_url );
	}


	/**
	 * Adds the geo fields to the registration form.
	 *
	 * @param object $errors
	 *
	 * @return void
	 */
	public function add_geo_fields( $errors ) {
		$output = '';

		// generate hidden fields
		foreach ( $this->geo_fields() as $key => $value ) {
			$output .= '<input type="hidden" name="' . esc_attr( $key ) . '" value="" />';
		}

		// generate js script
		$output .= '<script type="text/javascript">' . PHP_EOL;
		$output .= '  jQuery(document).ready(function($) {' . PHP_EOL;
		$output .= '    $.getJSON("'. esc_attr( $this->get_service_url() ) . '", function(json) {' . PHP_EOL;

		foreach ( $this->geo_fields_map() as $field_name => $response_key ) {
			$output .= '      $("[name=\''. esc_attr( $field_name ) . '\']").val(json.' . esc_attr( $response_key ) . ');' . PHP_EOL;
		}

		$output .= '    });' . PHP_EOL;
		$output .= '  });' . PHP_EOL;
		$output .= '</script>' . PHP_EOL;

		echo apply_filters( 'add_geo_fields', $output );
	}


	/**
	 * Saves all the geo values.
	 *
	 * @param int $user_id
	 *
	 * @return void
	 */
	public function save_geo_fields( $user_id ) {
		foreach ( $this->geo_fields() as $key => $value ) {
			$posted = isset( $_POST[ $key ] ) ? wp_kses_data( $_POST[ $key ] ) : '';
			update_user_meta( $user_id, $key, $posted );
		}
	}


	/**
	 * Saves all the geo values for multisite.
	 *
	 * @param array $meta
	 *
	 * @return array
	 */
	public function save_geo_fields_ms( $meta ) {
		foreach ( $this->geo_fields() as $key => $value ) {
			$posted = isset( $_POST[ $key ] ) ? wp_kses_data( $_POST[ $key ] ) : '';
			$meta[ $key ] = $posted;
		}

		return $meta;
	}


	/**
	 * Moves geo data from wp_signups into wp_usermeta table.
	 * Runs once activation link is clicked.
	 *
	 * @param int $user_id
	 * @param string $password
	 * @param array $meta
	 *
	 * @return void
	 */
	public function move_geo_fields_ms( $user_id, $password, $meta ) {
		foreach ( $this->geo_fields() as $key => $value ) {
			$posted = isset( $meta[ $key ] ) ? $meta[ $key ] : '';
			update_user_meta( $user_id, $key, $posted );
		}
	}


	/**
	 * Saves all the geo values for buddypress.
	 *
	 * @param int $user_id
	 * @param string $user_login
	 * @param string $user_password
	 * @param string $user_email
	 * @param array $usermeta
	 *
	 * @return void
	 */
	public function save_geo_fields_bp( $user_id, $user_login, $user_password, $user_email, $usermeta ) {
		foreach ( $this->geo_fields() as $key => $value ) {
			$posted = isset( $_POST[ $key ] ) ? wp_kses_data( $_POST[ $key ] ) : '';
			update_user_meta( $user_id, $key, $posted );
		}
	}


	/**
	 * Displays geo fields and map on admin edit user page.
	 *
	 * @param object $user
	 *
	 * @return void
	 */
	public function show_geo_fields( $user ) {
		$output = '';
		$i = 0;

		$map_q = esc_attr( get_the_author_meta( 'geoip_latitude', $user->ID ) ) . ',+' .
			esc_attr( get_the_author_meta( 'geoip_longitude', $user->ID ) ) . '+(' .
			esc_attr( get_the_author_meta( 'display_name', $user->ID ) ) . ')';

		$url = '//maps.google.com/maps?f=q&amp;geocode=&amp;q=' . $map_q . '&amp;hl=' . esc_attr( $this->wplang() ) . '&amp;output=embed&amp;iwloc=near&amp;z=6';

		$output .= '<h3>' . __( 'Geographic Info', 'georeg' ) . '</h3>';
		$output .= '<table class="form-table">';
		foreach ( $this->geo_fields() as $key => $value ) {
			$output .= '<tr><th><label for="' . esc_attr( $key ) . '">' . $value . '</label></th>';
			$output .= '<td width="325"><input type="text" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" value="' . esc_attr( get_the_author_meta( $key, $user->ID ) ) . '" class="regular-text" /></td>';
			if ( $i === 0 ) {
				$output .= '<td rowspan="' . count( $this->geo_fields() ) . '"><iframe width="425" height="325" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="' . esc_url( $url ) . '"></iframe><br /><small><a href="' . esc_url( $url ) . '&amp;iwloc=A" target="_blank">' . __( 'View Larger Map', 'georeg' ) . '</a></small></td>';
			}
			$output .= '</tr>';
			$i++;
		}
		$output .= '</table>';

		echo apply_filters( 'show_geo_fields', $output );
	}


	/**
	 * Adds custom user columns.
	 *
	 * @param array $columns
	 *
	 * @return array
	 */
	public function add_user_columns( $columns ) {
		foreach ( $this->geo_fields() as $key => $value ) {
			$columns[ $key ] = $value;
		}

		return $columns;
	}


	/**
	 * Returns values for custom user columns.
	 *
	 * @param string $val
	 * @param string $column_name
	 * @param int $user_id
	 *
	 * @return string
	 */
	function add_user_column_value( $val, $column_name, $user_id ) {
		foreach ( $this->geo_fields() as $key => $value ) {
			if ( $key == $column_name ) {
				return get_the_author_meta( $key, $user_id );
			}
		}

		return $val;
	}

}

// kick things off
new AT_GeoReg();

