array(
'type' => array(),
'id' => array(),
'name' => array(),
'value' => array(),
'class' => array(),
'placeholder' => array(),
'size' => array(),
)
);
// Holds the values to be used in the fields callbacks
private $rootPluginFilenameAndPath;
private $importableConfiguration;
/**
* Constructor
*
* @param mixed $rootPluginFilenameAndPath
*/
public function __construct( $rootPluginFilenameAndPath ) {
assert( ! empty( $rootPluginFilenameAndPath ) );
assert( PostmanUtils::isAdmin() );
assert( is_admin() );
$this->logger = new PostmanLogger( get_class( $this ) );
$this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
$this->options = PostmanOptions::getInstance();
$this->settingsRegistry = new PostmanSettingsRegistry();
// hook on the init event
add_action( 'init', array(
$this,
'on_init',
) );
// initialize the scripts, stylesheets and form fields
add_action( 'admin_init', array(
$this,
'on_admin_init',
) );
add_action( 'admin_menu', array( $this, 'add_submenu_page' ), 21 );
add_action( 'admin_menu', array( $this, 'addSetupWizardSubmenu' ), 21 );
add_filter( 'submenu_file', array( $this, 'hide_submenu_item' ) );
}
/**
* Functions to execute on the init event
*
* "Typically used by plugins to initialize. The current user is already authenticated by this time."
* ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_a_Typical_Request
*/
public function on_init() {
// register Ajax handlers
new PostmanGetHostnameByEmailAjaxController();
new PostmanManageConfigurationAjaxHandler();
new PostmanImportConfigurationAjaxController( $this->options );
}
/**
* Fires on the admin_init method
*/
public function on_admin_init() {
$this->registerStylesAndScripts();
$this->settingsRegistry->on_admin_init();
}
/**
* Register and add settings
*/
private function registerStylesAndScripts() {
if ( $this->logger->isTrace() ) {
$this->logger->trace( 'registerStylesAndScripts()' );
}
// register the stylesheet and javascript external resources
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
wp_register_script( 'postman_manual_config_script', plugins_url( 'Postman/Postman-Configuration/postman_manual_config.js', $this->rootPluginFilenameAndPath ), array(
PostmanViewController::JQUERY_SCRIPT,
'jquery-ui-core',
'jquery-ui-tabs',
'jquery_validation',
PostmanViewController::POSTMAN_SCRIPT,
), $pluginData ['version'] );
wp_register_script( 'postman_wizard_script', plugins_url( 'Postman/Postman-Configuration/postman_wizard.js', $this->rootPluginFilenameAndPath ), array(
PostmanViewController::JQUERY_SCRIPT,
'jquery_validation',
'jquery_steps_script',
PostmanViewController::POSTMAN_SCRIPT,
'sprintf',
), $pluginData ['version'] );
}
/**
*/
private function addLocalizeScriptsToPage() {
// the transport modules scripts
foreach ( PostmanTransportRegistry::getInstance()->getTransports() as $transport ) {
$transport->enqueueScript();
}
// we need data from port test
PostmanConnectivityTestController::addLocalizeScriptForPortTest();
}
/**
* Adds sub menu page `Settings`
*
* @since 2.1
* @version 1.0
*/
public function add_submenu_page() {
// only do this for administrators
if ( PostmanUtils::isAdmin() ) {
$this->logger->trace( 'created PostmanSettings admin menu item' );
$page = add_submenu_page(
PostmanViewController::POSTMAN_MENU_SLUG,
sprintf( __( '%s Setup', 'post-smtp' ), __( 'Postman SMTP', 'post-smtp' ) ),
__( 'Settings', 'post-smtp' ),
Postman::MANAGE_POSTMAN_CAPABILITY_NAME,
PostmanConfigurationController::CONFIGURATION_SLUG,
array(
$this,
'outputManualConfigurationContent',
) );
// When the plugin options page is loaded, also load the stylesheet
add_action( 'admin_print_styles-' . $page, array( $this, 'enqueueConfigurationResources' ) );
}
}
/**
*/
function enqueueConfigurationResources() {
$this->addLocalizeScriptsToPage();
wp_enqueue_style( 'jquery_ui_style' );
wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
wp_enqueue_script( 'postman_manual_config_script' );
}
/**
* Register the Setup Wizard screen
*/
public function addSetupWizardSubmenu() {
$page = add_submenu_page(
PostmanViewController::POSTMAN_MENU_SLUG,
sprintf( __( '%s Setup', 'post-smtp' ), __( 'Postman SMTP', 'post-smtp' ) ),
__( 'Postman SMTP', 'post-smtp' ),
Postman::MANAGE_POSTMAN_CAPABILITY_NAME,
PostmanConfigurationController::CONFIGURATION_WIZARD_SLUG,
array(
$this,
'outputWizardContent',
) );
// When the plugin options page is loaded, also load the stylesheet
add_action( 'admin_print_styles-' . $page, array(
$this,
'enqueueWizardResources',
) );
}
/**
* Hides submenu
*/
public function hide_submenu_item( $submenu_file ) {
$hidden_submenus = array(
PostmanConfigurationController::CONFIGURATION_WIZARD_SLUG => true,
);
// Hide the submenu.
foreach ( $hidden_submenus as $submenu => $unused ) {
remove_submenu_page( PostmanViewController::POSTMAN_MENU_SLUG, $submenu );
}
return $submenu_file;
}
/**
*/
function enqueueWizardResources() {
$this->addLocalizeScriptsToPage();
$this->importableConfiguration = new PostmanImportableConfiguration();
$startPage = 1;
if ( $this->importableConfiguration->isImportAvailable() ) {
$startPage = 0;
}
wp_localize_script( PostmanViewController::POSTMAN_SCRIPT, 'postman_setup_wizard', array(
'start_page' => $startPage,
) );
wp_enqueue_style( 'jquery_steps_style' );
wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
wp_enqueue_script( 'postman_wizard_script' );
wp_localize_script( 'postman_wizard_script', 'postman',
array(
'assets' => POST_SMTP_ASSETS
)
);
//wp_localize_script( PostmanViewController::POSTMAN_SCRIPT, '$jq', 'jQuery.noConflict(true)' );
$shortLocale = substr( get_locale(), 0, 2 );
if ( $shortLocale != 'en' ) {
$url = plugins_url( sprintf( 'script/jquery-validate/localization/messages_%s.js', $shortLocale ), $this->rootPluginFilenameAndPath );
wp_enqueue_script( sprintf( 'jquery-validation-locale-%s', $shortLocale ), $url, array(), POST_SMTP_VER );
}
}
/**
*/
public function outputManualConfigurationContent() {
print '
';
PostmanViewController::outputChildPageHeader( __( 'Settings', 'post-smtp' ), 'advanced_config' );
$config_tabs = apply_filters( 'post_smtp_admin_tabs', array(
'account_config' => __( 'Account', 'post-smtp' ),
'fallback' => __( 'Fallback', 'post-smtp' ),
'message_config' => __( 'Message', 'post-smtp' ),
'logging_config' => __( 'Logging', 'post-smtp' ),
'advanced_options_config' => __( 'Advanced', 'post-smtp' ),
) );
print '
';
foreach ( $config_tabs as $slug => $tab ) :
printf( '- %s
', esc_attr( $slug ), esc_html( $tab ) );
endforeach;
print '
';
print '
';
print '
';
print '
';
}
/**
*/
public function outputWizardContent() {
/**
* Filters whether to display the legacy wizard or not.
*
* @since 2.6.2
*/
if( apply_filters( 'post_smtp_legacy_wizard', true ) ) {
// Set default values for input fields
$this->options->setMessageSenderEmailIfEmpty( wp_get_current_user()->user_email );
$this->options->setMessageSenderNameIfEmpty( wp_get_current_user()->display_name );
// construct Wizard
print '';
PostmanViewController::outputChildPageHeader( __( 'Setup Wizard', 'post-smtp' ) );
print '
';
print '
';
}
else {
/**
* Fires to load new wizard
*
* @since 2.6.2
*/
do_action( 'post_smtp_new_wizard' );
}
}
}
/**
*
* @author jasonhendriks
*/
class PostmanGetHostnameByEmailAjaxController extends PostmanAbstractAjaxHandler {
const IS_GOOGLE_PARAMETER = 'is_google';
function __construct() {
parent::__construct();
PostmanUtils::registerAjaxHandler( 'postman_check_email', $this, 'getAjaxHostnameByEmail' );
}
/**
* This Ajax function retrieves the smtp hostname for a give e-mail address
*/
function getAjaxHostnameByEmail() {
check_admin_referer('post-smtp', 'security');
if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
wp_send_json_error(
array(
'Message' => 'Unauthorized.'
),
401
);
}
$goDaddyHostDetected = $this->getBooleanRequestParameter( 'go_daddy' );
$email = $this->getRequestParameter( 'email' );
$d = new PostmanSmtpDiscovery( $email );
$smtp = $d->getSmtpServer();
$this->logger->debug( 'given email ' . $email . ', smtp server is ' . $smtp );
$this->logger->trace( $d );
if ( $goDaddyHostDetected && ! $d->isGoogle ) {
// override with the GoDaddy SMTP server
$smtp = 'relay-hosting.secureserver.net';
$this->logger->debug( 'detected GoDaddy SMTP server, smtp server is ' . $smtp );
}
$response = array(
'hostname' => $smtp,
self::IS_GOOGLE_PARAMETER => $d->isGoogle,
'is_go_daddy' => $d->isGoDaddy,
'is_well_known' => $d->isWellKnownDomain,
);
$this->logger->trace( $response );
wp_send_json_success( $response );
}
}
class PostmanManageConfigurationAjaxHandler extends PostmanAbstractAjaxHandler {
function __construct() {
parent::__construct();
PostmanUtils::registerAjaxHandler( 'manual_config', $this, 'getManualConfigurationViaAjax' );
PostmanUtils::registerAjaxHandler( 'get_wizard_configuration_options', $this, 'getWizardConfigurationViaAjax' );
}
/**
* Handle a Advanced Configuration request with Ajax
*
* @throws Exception
*/
function getManualConfigurationViaAjax() {
check_admin_referer('post-smtp', 'security');
if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
wp_send_json_error(
array(
'Message' => 'Unauthorized.'
),
401
);
}
$queryTransportType = $this->getTransportTypeFromRequest();
$queryAuthType = $this->getAuthenticationTypeFromRequest();
$queryHostname = $this->getHostnameFromRequest();
// the outgoing server hostname is only required for the SMTP Transport
// the Gmail API transport doesn't use an SMTP server
$transport = PostmanTransportRegistry::getInstance()->getTransport( $queryTransportType );
if ( ! $transport ) {
throw new Exception( 'Unable to find transport ' . $queryTransportType );
}
// create the response
$response = $transport->populateConfiguration( $queryHostname );
$response ['referer'] = 'manual_config';
// set the display_auth to oauth2 if the transport needs it
if ( $transport->isOAuthUsed( $queryAuthType ) ) {
$response ['display_auth'] = 'oauth2';
$this->logger->debug( 'ajaxRedirectUrl answer display_auth:' . $response ['display_auth'] );
}
$this->logger->trace( $response );
wp_send_json_success( $response );
}
/**
* Once the Port Tests have run, the results are analyzed.
* The Transport place bids on the sockets and highest bid becomes the recommended
* The UI response is built so the user may choose a different socket with different options.
*/
function getWizardConfigurationViaAjax() {
check_admin_referer('post-smtp', 'security');
if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
wp_send_json_error(
array(
'Message' => 'Unauthorized.'
),
401
);
}
$this->logger->debug( 'in getWizardConfiguration' );
$originalSmtpServer = $this->getRequestParameter( 'original_smtp_server' );
$queryHostData = $this->getHostDataFromRequest();
$sockets = array();
foreach ( $queryHostData as $id => $datum ) {
array_push( $sockets, new PostmanWizardSocket( $datum ) );
}
$this->logger->error( $sockets );
$userPortOverride = $this->getUserPortOverride();
$userAuthOverride = $this->getUserAuthOverride();
// determine a configuration recommendation
$winningRecommendation = $this->getWinningRecommendation( $sockets, $userPortOverride, $userAuthOverride, $originalSmtpServer );
if ( $this->logger->isTrace() ) {
$this->logger->trace( 'winning recommendation:' );
$this->logger->trace( $winningRecommendation );
}
// create the reponse
$response = array();
$configuration = array();
$response ['referer'] = 'wizard';
if ( isset( $userPortOverride ) || isset( $userAuthOverride ) ) {
$configuration ['user_override'] = true;
}
if ( isset( $winningRecommendation ) ) {
// create an appropriate (theoretical) transport
$transport = PostmanTransportRegistry::getInstance()->getTransport( $winningRecommendation ['transport'] );
// create user override menu
$overrideMenu = $this->createOverrideMenus( $sockets, $winningRecommendation, $userPortOverride, $userAuthOverride );
if ( $this->logger->isTrace() ) {
$this->logger->trace( 'override menu:' );
$this->logger->trace( $overrideMenu );
}
$queryHostName = $winningRecommendation ['hostname'];
if ( $this->logger->isDebug() ) {
$this->logger->debug( 'Getting scribe for ' . $queryHostName );
}
$generalConfig1 = $transport->populateConfiguration( $queryHostName );
$generalConfig2 = $transport->populateConfigurationFromRecommendation( $winningRecommendation );
$configuration = array_merge( $configuration, $generalConfig1, $generalConfig2 );
$response ['override_menu'] = $overrideMenu;
$response ['configuration'] = $configuration;
if ( $this->logger->isTrace() ) {
$this->logger->trace( 'configuration:' );
$this->logger->trace( $configuration );
$this->logger->trace( 'response:' );
$this->logger->trace( $response );
}
wp_send_json_success( $response );
} else {
/* translators: where %s is the URL to the Connectivity Test page */
$configuration ['message'] = sprintf( __( 'Postman can\'t find any way to send mail on your system. Run a connectivity test.', 'post-smtp' ), PostmanViewController::getPageUrl( PostmanConnectivityTestController::PORT_TEST_SLUG ) );
$response ['configuration'] = $configuration;
if ( $this->logger->isTrace() ) {
$this->logger->trace( 'configuration:' );
$this->logger->trace( $configuration );
}
wp_send_json_error( $response );
}
}
/**
* // for each successful host/port combination
* // ask a transport if they support it, and if they do at what priority is it
* // configure for the highest priority you find
*
* @param mixed $queryHostData
* @return mixed
*/
private function getWinningRecommendation( $sockets, $userSocketOverride, $userAuthOverride, $originalSmtpServer ) {
foreach ( $sockets as $socket ) {
$winningRecommendation = $this->getWin( $socket, $userSocketOverride, $userAuthOverride, $originalSmtpServer );
$this->logger->error( $socket->label );
}
return $winningRecommendation;
}
/**
*
* @param PostmanWizardSocket $socket
* @param mixed $userSocketOverride
* @param mixed $userAuthOverride
* @param mixed $originalSmtpServer
* @return mixed
*/
private function getWin( PostmanWizardSocket $socket, $userSocketOverride, $userAuthOverride, $originalSmtpServer ) {
static $recommendationPriority = - 1;
static $winningRecommendation = null;
$available = $socket->success;
if ( $available ) {
$this->logger->debug( sprintf( 'Asking for judgement on %s:%s', $socket->hostname, $socket->port ) );
$recommendation = PostmanTransportRegistry::getInstance()->getRecommendation( $socket, $userAuthOverride, $originalSmtpServer );
$recommendationId = sprintf( '%s_%s', $socket->hostname, $socket->port );
$recommendation ['id'] = $recommendationId;
$this->logger->debug( sprintf( 'Got a recommendation: [%d] %s', $recommendation ['priority'], $recommendationId ) );
if ( isset( $userSocketOverride ) ) {
if ( $recommendationId == $userSocketOverride ) {
$winningRecommendation = $recommendation;
$this->logger->debug( sprintf( 'User chosen socket %s is the winner', $recommendationId ) );
}
} elseif ( $recommendation && $recommendation ['priority'] > $recommendationPriority ) {
$recommendationPriority = $recommendation ['priority'];
$winningRecommendation = $recommendation;
}
$socket->label = $recommendation ['label'];
}
return $winningRecommendation;
}
/**
*
* @param mixed $queryHostData
* @return multitype:
*/
private function createOverrideMenus( $sockets, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
$overrideMenu = array();
$last_items = array();
foreach ( $sockets as $socket ) {
$overrideItem = $this->createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
if ( $overrideItem != null ) {
$transport = PostmanTransportRegistry::getInstance()->getTransport( $socket->transport );
//If class has constant
if( defined( get_class( $transport ) . "::PRIORITY" ) ) {
$priority = $transport::PRIORITY;
$overrideMenu[$priority] = $overrideItem;
}
else {
$last_items[] = $overrideItem;
}
}
}
//Sort in DESC order
krsort( $overrideMenu );
//Start Placing sockets in last, because they don't have there own priority.
foreach( $last_items as $item ) {
$overrideMenu[] = $item;
}
$menu = array();
foreach ( $overrideMenu as $key ) {
array_push( $menu, $key );
}
return $menu;
}
/**
*
* @param PostmanWizardSocket $socket
* @param mixed $winningRecommendation
* @param mixed $userSocketOverride
* @param mixed $userAuthOverride
*/
private function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
if ( $socket->success ) {
$transport = PostmanTransportRegistry::getInstance()->getTransport( $socket->transport );
$this->logger->debug( sprintf( 'Transport %s is building the override menu for socket', $transport->getSlug() ) );
$overrideItem = $transport->createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
return $overrideItem;
}
return null;
}
/**
*/
private function getTransportTypeFromRequest() {
return $this->getRequestParameter( 'transport' );
}
/**
*/
private function getHostnameFromRequest() {
return $this->getRequestParameter( 'hostname' );
}
/**
*/
private function getAuthenticationTypeFromRequest() {
return $this->getRequestParameter( 'auth_type' );
}
/**
*/
private function getHostDataFromRequest() {
return $this->getRequestParameter( 'host_data' );
}
/**
*/
private function getUserPortOverride() {
return $this->getRequestParameter( 'user_port_override' );
}
/**
*/
private function getUserAuthOverride() {
return $this->getRequestParameter( 'user_auth_override' );
}
}
class PostmanImportConfigurationAjaxController extends PostmanAbstractAjaxHandler {
private $options;
/**
* Constructor
*
* @param PostmanOptions $options
*/
function __construct( PostmanOptions $options ) {
parent::__construct();
$this->options = $options;
PostmanUtils::registerAjaxHandler( 'import_configuration', $this, 'getConfigurationFromExternalPluginViaAjax' );
}
/**
* This function extracts configuration details form a competing SMTP plugin
* and pushes them into the Postman configuration screen.
*/
function getConfigurationFromExternalPluginViaAjax() {
check_admin_referer('post-smtp', 'security');
if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
wp_send_json_error(
array(
'Message' => 'Unauthorized.'
),
401
);
}
$importableConfiguration = new PostmanImportableConfiguration();
$plugin = $this->getRequestParameter( 'plugin' );
$this->logger->debug( 'Looking for config=' . $plugin );
foreach ( $importableConfiguration->getAvailableOptions() as $this->options ) {
if ( $this->options->getPluginSlug() == $plugin ) {
$this->logger->debug( 'Sending configuration response' );
$response = array(
PostmanOptions::MESSAGE_SENDER_EMAIL => $this->options->getMessageSenderEmail(),
PostmanOptions::MESSAGE_SENDER_NAME => $this->options->getMessageSenderName(),
PostmanOptions::HOSTNAME => $this->options->getHostname(),
PostmanOptions::PORT => $this->options->getPort(),
PostmanOptions::AUTHENTICATION_TYPE => $this->options->getAuthenticationType(),
PostmanOptions::SECURITY_TYPE => $this->options->getEncryptionType(),
PostmanOptions::BASIC_AUTH_USERNAME => $this->options->getUsername(),
PostmanOptions::BASIC_AUTH_PASSWORD => $this->options->getPassword(),
'success' => true,
);
break;
}
}
if ( ! isset( $response ) ) {
$response = array(
'success' => false,
);
}
wp_send_json( $response );
}
}