HEX
Server: Apache/2.4.25
System: Linux ion14 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3.1 (2019-02-19) x86_64
User: (10087)
PHP: 7.4.30
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,system, exec, shell_exec, passthru, popen, proc_open
Upload Files
File: /home/www/web115/wordpress/wp-content/plugins/digimember/system/model/logic/action.php
<?php

class ncore_ActionLogic extends ncore_BaseLogic
{
    function actionExpireDays( $condition_type=false )
    {
        $default_days = 120;

        $condition_type_days_map = array(
            'page_view'    => 60,
            'login'        => 30,
            'paused'       => 60,
            'never_online' => 60,
            'prd_expired'  => 21,
            'new_content'  => 7,
        );

        return $condition_type === 'all'
               ? $condition_type_days_map
               : ($condition_type
                  ? ncore_retrieve( $condition_type_days_map, $condition_type, $default_days )
                  : $default_days);
    }

    function validateUnsubscribeKey( $unsubscribe_key )
    {
        if (!$unsubscribe_key) {
            return false;
        }

        list( $user_id,  ) = ncore_retrieveList( '_', $unsubscribe_key, 2, true );

        if (!is_numeric($user_id) || $user_id<=0) {
            return false;
        }

        $epxected_key = $this->unsubscribeKey( $user_id );

        $this->api->load->helper( 'encryption' );
        $is_valid = ncore_hashCompare( $unsubscribe_key, $epxected_key );

        return $is_valid
               ? $user_id
               : false;
    }

    function renderQueueActionJs( $email_or_wp_user_id, $action )
    {
        $signature = $this->_actionSignature( $email_or_wp_user_id, $action->id );

        /** @var digimember_LinkLogic $link */
        $link = $this->api->load->model( 'logic/link' );

        $args = array(
                'action_id' => $action->id,
                'signature' => $signature,
                'user_id'   => $email_or_wp_user_id,
                );

        $url = $link->ajaxUrl( 'ajax/misc', 'action_delayed', $args );

        $js = "dmDialogAjax_FetchUrl( '$url', do_omit_waiting=true );";

        return $js;

    }

    function conditionOptions()
    {
        $options = array(
            'page_view'    => _ncore( 'by viewing a page' ),
            'login'        => _ncore( 'by a login' ),
            'paused'       => _ncore( 'after paused using this website' ),
            'never_online' => _ncore( 'if never logged in' ),
            'prd_expired'  => _ncore( 'if product access expires' ),
            'new_content'  => _digi( 'if user has access to new content' ),
        );

        if (!DIGIMEMBER_HAVE_NEW_CONTENT_ACTION)
        {
            unset( $options[ 'new_content' ] );
        }

        return $options;
    }

    function queueAction( $action_list_or_action, $wp_user_id_or_email, $is_test_run=false )
    {
        $this->_queueAction( $action_list_or_action, $wp_user_id_or_email, $is_test_run );
    }

    function onNewContent($user_id, /** @noinspection PhpUnusedParameterInspection */ $product_id )
    {
        if (!DIGIMEMBER_HAVE_NEW_CONTENT_ACTION)
        {
            return;
        }

        $where = array();

        $where[ 'is_active' ] = 'Y';
        $where[ 'condition_type' ] = 'new_content';

        $this->_queueActionsWhere( $where, $user_id );
    }

    function onLogin( $user_id,  $login_count, $last_login)
    {
        $where = array();
        $where[ 'is_active' ] = 'Y';
        $where[ 'condition_type' ] = 'login';
        $where[ 'condition_login_count <=' ] = $login_count;

        if ($login_count>=5) {
            $where[ 'condition_login_count >' ] = $login_count-5;
        }

        $days_since_login = max( 0, round( (ncore_unixDate() - ncore_unixDate( $last_login )) / 86400 ) );
        $where[ 'condition_login_after_days <=' ] = $days_since_login;

        $this->_queueActionsWhere( $where, $user_id );
    }

    function onPageView( $user_id,  $wp_page )
    {
        $where = array();
        $where[ 'is_active' ] = 'Y';
        $where[ 'condition_type' ] = 'page_view';
        $where[ 'condition_page' ] = $wp_page->ID;

        /** @var ncore_ActionData $actionData */
        $actionData = $this->api->load->model( 'data/action' );
        $all = $actionData->getAll( $where );

        foreach ($all as $one)
        {
            /** @var ncore_ActionOutQueue $model */
            $model       = $this->api->load->model( 'queue/action_out' );
            $have_action = $model->haveUnexpiredAction( $user_id, $one->id );


            if (!$have_action)
            {
                $call = $this->renderQueueActionJs( $user_id, $one );

                $is_delayed = $one->condition_page_view_time > 0;

                if ($is_delayed)
                {
                    $delay = $one->condition_page_view_time * 1000;

                    $js = "window.setTimeout(function(){ $call }, $delay );";
                }
                else
                {
                    $js = $call;
                }

                /** @var ncore_HtmlLogic $html */
                $html = $this->api->load->model( 'logic/html' );

                $html->jsOnLoad( $js );
            }
        }
    }

    function cronMinutely()
    {
        $this->_queuePausedUsingSiteActions();
        $this->_queueNeverLoggedinActions();
    }

    function cronDaily()
    {
        // empty
    }

    function queueDelayedAction( $email_or_wp_user_id, $action_id, $signature ) {

        $expected_sig = $this->_actionSignature( $email_or_wp_user_id, $action_id );

        $is_valid = ncore_hashCompare( $signature, $expected_sig );
        if (!$is_valid) {
            return;
        }

        $where = array();
        $where[ 'id' ]             = $action_id;
        $where[ 'is_active' ]      = 'Y';

        $this->_queueActionsWhere( $where, $email_or_wp_user_id );
    }

    function statusOptions()
    {
        return array(
            'skipped' => '-',
            'error'   => _ncore( 'Error' ),
            'success' => _digi( 'Sent' ),

            'kt_no_contact'      => _digi( '(Not a subscriber)' ),
            'webpush_no_contact' => _digi( '(Not a subscriber)' ),
            'webpush_no_message' => _digi( '(No push notification setup)' ),
            'email_optout'       => _digi( '(Not a subscriber)' ),
        );
    }

    function execute( $wp_user_id_or_email, $action_obj_or_id )
    {
        $result = array(
            'klicktipp_status' => '',
            'webpush_status'   => '',
            'email_status'     => '',
        );

        /** @var ncore_ActionData $model */
        $model = $this->api->load->model( 'data/action' );

        $action = $model->resolveToObj( $action_obj_or_id );

        if (!$action) {
            /** @noinspection PhpUnhandledExceptionInspection */
            throw new Exception( "Invalid action object or id." );
        }

        $have_klicktipp = $action->klicktipp_is_active == 'Y';
        $have_webpush   = $action->webpush_is_active   == 'Y';
        $have_email     = $action->email_is_active     == 'Y';

        $result[ 'klicktipp_status' ] = $have_klicktipp
                                      ? $this->_executeKlicktipp( $wp_user_id_or_email, $action )
                                      : 'skipped';

        $result[ 'webpush_status' ] = $have_webpush
                                    ? $this->_executeWebpush( $wp_user_id_or_email, $action )
                                    : 'skipped';

        if ($action->email_is_sent_if_push_is_sent == 'N' && $result[ 'webpush_status' ] == 'success')
        {
            $have_email = false;
        }

        $result[ 'email_status' ] = $have_email
                                  ? $this->_executeEmail( $wp_user_id_or_email, $action )
                                  : 'skipped';

        return $result;

    }

    public function placeholders( $user_obj_or_id = false )
    {
        $user = ncore_getUserById( $user_obj_or_id );

        $first_name = '';
        $last_name  = '';

        if ($user)
        {
            $user_id = ncore_retrieve( $user, array( 'ID', 'id' ) );

            $first_name = get_user_meta( $user_id, "first_name", true );
            $last_name  = get_user_meta( $user_id, "last_name",  true );

            if (!$first_name) {
                $first_name = ncore_retrieve( $user, "display_name" );
                $last_name  = '';
            }
        }

        $placeholders = array(
            '[FIRST_NAME]' => $first_name,
            '[LAST_NAME]'  => $last_name,
        );

        if ($user)
        {
            $url = $this->emailUnsubscribeUrl( $user );

            $placeholders[ '[UNSUBSCRIBE]' ]  = "<a href=\"$url\">";
            $placeholders[ '[/UNSUBSCRIBE]' ] = '</a>';
        }


        return $placeholders;
    }


    public function defaultEmailImprint()
    {
        $find = array( '<a>', '</a>' );
        $repl = array( '[UNSUBSCRIBE]', '[/UNSUBSCRIBE]' );

        $shortcode = str_replace( $find, $repl, _dgyou( '<a>Click here</a> to unsubscribe.' ) );

        return $shortcode;
    }


    //
    // private4
    //

    private function _queueActionsWhere( $where, $email_or_wp_user_id )
    {
        $is_upgrading = defined( 'WP_INSTALLING' ) && WP_INSTALLING;
        if ($is_upgrading) {
            return;
        }

        /** @var ncore_ActionData $actionData */
        $actionData = $this->api->load->model( 'data/action' );
        $all = $actionData->getAll( $where );

        $this->_queueAction( $all, $email_or_wp_user_id );
    }

    function _queueAction( $action_list_or_action, $user_id, $is_test_run=false )
    {
        if (empty($action_list_or_action)) {
            return;
        }

        $action_list = is_object($action_list_or_action)
                     ? array( $action_list_or_action)
                     : $action_list_or_action;

        /** @var ncore_ActionOutQueue $actionOutQueue */
        $actionOutQueue = $this->api->load->model( 'queue/action_out' );

        /** @var digimember_UserProductData $user_product_model */
        $user_product_model = $this->api->load->model( 'data/user_product' );

        foreach ($action_list as $one)
        {
            if (!is_numeric( $user_id ) && !$is_test_run) {

                if (!isset( $wp_user_id)) {
                    $user = get_user_by( 'email', $user_id );
                    $wp_user_id = ncore_retrieve( $user, 'ID', false );
                }

                if ($wp_user_id) {
                    $resolved_user_id = $wp_user_id;
                }
                else {
                    continue;
                }
            }
            else {
                $resolved_user_id = $user_id;
            }

            $product_ids = $one->condition_product_ids_comma_seperated;

            if ($product_ids && $product_ids !== 'none' && !$is_test_run) {

                if (!$user_product_model->hasProduct( $resolved_user_id, $product_ids )) {
                    continue;
                }
            }

            $actionOutQueue->addJob( $resolved_user_id, $one, $is_test_run );
        }
    }


    private function _executeKlicktipp( $wp_user_id_or_email, $action )
    {
        try
        {
            $email = $this->_resolveUserToEmail( $wp_user_id_or_email );

            /** @var digimember_AutoresponderHandlerLib $lib */
            $lib = $this->api->load->library( 'autoresponder_handler' );

            $success = $lib->setTags( $action->klicktipp_ar_id, $email, $action->klicktipp_tags_add, $action->klicktipp_tags_remove );

            return $success
                   ? 'success'
                   : 'kt_no_contact';
        }
        catch (Exception $e)
        {
            $msg = $e->getMessage();

            $this->api->logError( 'ipn', _ncore( 'Failed to set tags for %s in KlickTipp: %s', $email, $msg ) );

            return 'error';
        }
    }

    private function _executeWebpush( $wp_user_id_or_email, $action )
    {
        $user_id = ncore_userId( $wp_user_id_or_email );
        if (!$user_id) {
            return 'webpush_no_contact';
        }

        /** @var digimember_WebpushLogic $webpushLogic */
        $webpushLogic = $this->api->load->model( 'logic/webpush' );
        /** @var digimember_WebpushMessageData $webpushMessageData */
        $webpushMessageData = $this->api->load->model( 'data/webpush_message' );
        try
        {
            $message = $webpushMessageData->get( $action->webpush_message_id );
            if (!$message) {
                return 'webpush_no_message';
            }

            $webpushLogic->sendNotificationToUser( $user_id, $message );
            return 'success';
        }

        catch (Exception $e)
        {
            $user = ncore_getUserById( $user_id );
            $name = ncore_retrieve( $user, 'user_login', 'User #'.$user_id );
            $this->api->logError( 'mail', _digi( 'Error sending web push message to %s: %s', $name, $e->getMessage()  ) );

            return 'error';
        }
    }


    public function doOptOutFromEmail( $wp_user_id_or_email='current', $do_optout = true )
    {
        /** @var ncore_UserSettingsData $model */
        $model = $this->api->load->model( 'data/user_settings' );

        $new_val = ncore_isTrue( $do_optout )
                 ? 'Y'
                 : false;

        $model->setForUser( $wp_user_id_or_email, 'has_action_email_optout', $new_val);
    }

    public function isOptedOutFromEmail( $wp_user_id_or_email='current' )
    {
        /** @var ncore_UserSettingsData $model */
        $model = $this->api->load->model( 'data/user_settings' );

        $has_opt_out = ncore_isTrue( $model->getForUser( $wp_user_id_or_email, 'has_action_email_optout', 'N' ) );

        return $has_opt_out;
    }

    private function _executeEmail( $wp_user_id_or_email, $action )
    {
        $email = $this->_resolveUserToEmail( $wp_user_id_or_email );
        if (!$email) {
            return 'email_no_contact';
        }


        /** @var ncore_MailerLib $mailer */
        $mailer = $this->api->load->library( 'mailer' );

        $has_opt_out = $this->isOptedOutFromEmail( $wp_user_id_or_email );
        if ($has_opt_out) {
            return 'email_optout';
        }

        $ph   = $this->placeholders( $wp_user_id_or_email );


        $body = wpautop( $action->email_body );

        /** @var digimember_BlogConfigLogic $blogConfigLogic */
        $blogConfigLogic = $this->api->load->model('logic/blog_config');
        $imprint = $blogConfigLogic->get( 'action_email_imprint' );
        if (!$imprint) {
            $imprint = $this->defaultEmailImprint();
        }
        $body .= wpautop( $imprint );

        $subject = str_ireplace( array_keys( $ph ), array_values( $ph ), $action->email_subject );
        $body    = str_ireplace( array_keys( $ph ), array_values( $ph ), $body );

        $mailer->to( $email );
        $mailer->subject( $subject );
        $mailer->html( $body );

        $success = $mailer->send();

        return $success
               ? 'success'
               : 'error';
    }


    private function _actionSignature( $email_or_wp_user_id, $action_id )
    {
        $user_id = $email_or_wp_user_id;

        /** @var ncore_UserSettingsData $model */
        $model = $this->api->load->model( 'data/user_settings' );

        $action_pw = $model->getForUser( $user_id, 'action_pw' );
        if (!$action_pw)
        {
            $this->api->load->helper( 'string' );
            $action_pw = ncore_randomString( 'alnum', 64 );
            $model->setForUser( $user_id, 'action_pw', $action_pw );
        }

        $secret = $action_id.'_'.$action_pw;

        $this->api->load->helper( 'encryption' );
        /** @noinspection PhpUnusedLocalVariableInspection */
        list( $algo, $signature ) = ncore_hash( $secret );

        return $signature;
    }

    private function _queuePausedUsingSiteActions()
    {
        /** @var ncore_ActionData $actionData */
        $actionData = $this->api->load->model( 'data/action' );
        $where = array();
        $where[ 'is_active' ] = 'Y';
        $where[ 'condition_type' ] = 'paused';
        $actions = $actionData->getAll( $where );
        if (!$actions) {
            return;
        }

        $min_paused_days = false;
        $max_paused_days = 1;

        foreach ($actions as $one)
        {
            if ($min_paused_days === false
                || $one->condition_paused_days<$min_paused_days)
            {
                $min_paused_days = $one->condition_paused_days;
            }

            if ($one->condition_paused_days>$max_paused_days)
            {
                $max_paused_days = $one->condition_paused_days;
            }
        }


        $last_login_before = ncore_dbDate( time()-86400*$min_paused_days );

        $grade_days = 30;
        $last_login_after  = ncore_dbDate( time()-86400*($max_paused_days+$grade_days) );

        $where = array();
        $where[ 'name'] = 'login';
        $where[ 'modified <='] = $last_login_before;
        $where[ 'modified >='] = $last_login_after;

        /** @var digimember_CounterData $model */
        $model = $this->api->load->model( 'data/counter' );
        $counts = $model->getAll( $where );

        $now = ncore_unixDate();
        foreach ($counts as $one_count)
        {
            $user_id = $one_count->user_id;

            $login_date = $one_count->modified;

            $paused_days = round( ($now-ncore_unixDate($login_date)) / 86400 );

            foreach ($actions as $one_action)
            {
                if ($one_action->condition_paused_days <= $paused_days
                    && $one_action->condition_paused_days >= $paused_days - $grade_days)
                {
                    $this->_queueAction( $one_action, $user_id );
                }
            }
        }

    }

    private function _queueNeverLoggedinActions()
    {
        /** @var ncore_ActionData $actionData */
        $actionData = $this->api->load->model( 'data/action' );
        $where = array();
        $where[ 'is_active' ] = 'Y';
        $where[ 'condition_type' ] = 'never_online';
        $actions = $actionData->getAll( $where );
        if (!$actions) {
            return;
        }

        $min_days = false;
        $max_days = 1;

        foreach ($actions as $one)
        {
            if ($min_days === false
                || $one->condition_never_online_days<$min_days)
            {
                $min_days = $one->condition_never_online_days;
            }

            if ($one->condition_never_online_days>$max_days)
            {
                $max_days = $one->condition_never_online_days;
            }
        }

        /** @var digimember_CounterData $model */
        $model = $this->api->load->model( 'data/counter' );
        $grace_days=30;
        $user_id_age_map = $model->getUserIdsNotLoggedIn( $min_days, $max_days+$grace_days );

        foreach ($user_id_age_map as $user_id => $age_in_days)
        {
            foreach ($actions as $one_action)
            {
                if ($one_action->condition_never_online_days <= $age_in_days
                    && $one_action->condition_never_online_days >= $age_in_days-$grace_days)
                {
                    $this->_queueAction( $one_action, $user_id );
                }
            }
        }
    }


    private function _resolveUserToEmail( $wp_user_id_or_email )
    {
        if (is_numeric($wp_user_id_or_email))
        {
            $user = ncore_getUserByid( $wp_user_id_or_email );
            return $user
                   ? $user->user_email
                   : false;
        }

        $is_email = is_string( $wp_user_id_or_email ) && strpos( $wp_user_id_or_email, '@' ) !== false;
        if ($is_email) {
            return $wp_user_id_or_email;
        }

        return ncore_retrieve( $wp_user_id_or_email, array( 'user_email', 'email' ), false );
    }

    private function unsubscribeKey( $user_obj_or_id )
    {
        /** @var ncore_UserSettingsData $userSettingsData */
        $userSettingsData = $this->api->load->model( 'data/user_settings' );

        $user_id = ncore_userid( $user_obj_or_id );
        if (!$user_id) {
            return '';
        }

        $key = $userSettingsData->getForUser( $user_id, 'action_unsub_key' );
        if (!$key) {
            $this->api->load->helper( 'string' );
            $key = ncore_randomString( 'password', 20 );

            $userSettingsData->setForUser( $user_id, 'action_unsub_key', $key );
        }

        return $user_id. '_' . $key;
    }

    private function emailUnsubscribeUrl( $user )
    {
        $key = $this->unsubscribeKey( $user );
        return ncore_addArgs( site_url(), array( 'dm_manage_subscriptions' => $key ) );
    }



}