function Users_0_9_2_Users_mysql()
{
    $app = Q_Config::expect('Q', 'app');
    $communityId = Users::communityId();
    $rows = Users_Session::select('COUNT(1)')->where($criteria)->fetchAll(PDO::FETCH_NUM);
    $count = $rows[0][0];
    $limit = 100;
    $offset = 0;
    $sessions = Users_Session::select('*')->orderBy('id')->limit($limit, $offset)->caching(false)->fetchDbRows();
    echo "Adding userId to sessions...";
    while ($sessions) {
        foreach ($sessions as $s) {
            $parsed = Q::json_decode($s->content, true);
            if (empty($parsed['Users']['loggedInUser']['id'])) {
                continue;
            }
            $s->userId = $parsed['Users']['loggedInUser']['id'];
        }
        Users_Session::insertManyAndExecute($sessions, array('onDuplicateKeyUpdate' => array('userId' => new Db_Expression("VALUES(userId)"))));
        $min = min($offset + $limit, $count);
        echo "";
        echo "Updated {$min} of {$count} sessions";
        $offset += $limit;
        if ($offset > $count) {
            break;
        }
        $sessions = Users_Session::select('*')->orderBy('id')->limit($limit, $offset)->caching(false)->fetchDbRows();
    }
    echo "\n";
}
 /**
  * Call this in your helpers to parse the args into a useful array
  * @method parseArgs
  * @static
  * @param {Handlebars_Template} $template
  * @param {Handlebars_Context} $context
  * @param {string|array} $args
  * @return {array}
  */
 static function parseArgs($template, $context, $args)
 {
     if (is_array($args)) {
         return $args;
     }
     $parsed = array_merge($template->parseArguments($args), $template->parseNamedArguments($args));
     $results = array();
     foreach ($parsed as $k => $arg) {
         $result = $context->get($arg);
         if (!isset($result)) {
             try {
                 $result = Q::json_decode($arg);
             } catch (Exception $e) {
             }
         }
         $results[$k] = $result;
     }
     return $results;
 }
Exemple #3
0
function Users_sessions_delete()
{
    if (empty($_REQUEST["sessionId"])) {
        throw new Q_Exceptions_RequiredField(array('field' => 'sessionId'));
    }
    $session = new Users_Session();
    $session->id = $_REQUEST['sessionId'];
    $session->retrieve(true);
    $content = Q::json_decode($session->content);
    $userId = Q::ifset($content, 'Users', 'loggedInUser', 'id', null);
    $loggedInUserId = Users::loggedInUser(true)->id;
    if ($userId == $loggedInUserId) {
        $authorized = true;
    } else {
        $app = Q::app();
        $roles = Users::roles();
        $authorized = !empty($roles["{$app}/admins"]);
    }
    if (!$authorized) {
        throw new Users_Exception_NotAuthorized();
    }
    $session->remove();
    Q_Response::setSlot('success', true);
}
Exemple #4
0
function Streams_form_post($params = array())
{
    if (empty($_REQUEST['inputs'])) {
        throw new Q_Exception_RequiredField(array('field' => 'inputs'));
    }
    $inputs = Q::json_decode($_REQUEST['inputs'], true);
    $user = Users::loggedInUser(true);
    $r = array_merge($_REQUEST, $params);
    $streams = array();
    foreach ($inputs as $name => $info) {
        $inputName = "input_{$name}";
        if (!isset($r[$inputName])) {
            continue;
        }
        if (!is_array($info) or count($info) < 4) {
            throw new Q_Exception_WrongValue(array('field' => 'inputs', 'range' => 'array of name => (streamExists, publisherId, streamName, fieldName)'));
        }
        list($streamExists, $publisherId, $streamName, $fieldName) = $info;
        $stream = Streams::fetchOne(null, $publisherId, $streamName);
        if (!$stream) {
            if ($user->id !== $publisherId or !Q_Config::get('Streams', 'possibleUserStreams', $streamName, false)) {
                throw new Users_Exception_NotAuthorized();
            }
            $stream = Streams::create(null, $publisherId, null, array('name' => $streamName));
        }
        $attribute = substr($fieldName, 0, 10) === 'attribute:' ? substr($fieldName, 10) : null;
        if ($attribute) {
            $stream->setAttribute($attribute, $r[$inputName]);
        } else {
            $stream->{$fieldName} = $r[$inputName];
        }
        $stream->save();
        $streams[$stream->name] = $stream;
    }
    Q_Response::setSlot('streams', Db::exportArray($streams));
}
Exemple #5
0
 /**
  * Get autocomplete results
  * @method autocomplete
  * @static
  * @param {string} $input The text (typically typed by a user) to find completions for
  * @param {boolean} [$throwIfBadValue=false]
  *  Whether to throw Q_Exception if the result contains a bad value
  * @param {array} [$types=array("establishment")] Can include "establishment", "locality", "sublocality", "postal_code", "country", "administrative_area_level_1", "administrative_area_level_2". Set to true to include all types.
  * @param {double} [$latitude=userLocation] Override the latitude of the coordinates to search around
  * @param {double} [$longitude=userLocation] Override the longitude of the coordinates to search around
  * @param {double} [$miles=25] Override the radius, in miles, to search around
  * @return {Streams_Stream|null}
  * @throws {Q_Exception} if a bad value is encountered and $throwIfBadValue is true
  */
 static function autocomplete($input, $throwIfBadValue = false, $types = null, $latitude = null, $longitude = null, $miles = 25)
 {
     $supportedTypes = array("establishment", "locality", "sublocality", "postal_code", "country", "administrative_area_level_1", "administrative_area_level_2");
     $input = strtolower($input);
     if (is_string($types)) {
         $types = explode(',', $types);
     } else {
         if ($types === true) {
             $types = null;
         }
     }
     if ($types) {
         foreach ($types as $type) {
             if (!in_array($type, $supportedTypes)) {
                 throw new Q_Exception_BadValue(array('internal' => '$types', 'problem' => "{$type} is not supported"));
             }
         }
     }
     if (empty($input)) {
         if ($throwIfBadValue) {
             throw new Q_Exception_RequiredField(array('field' => 'input'));
         }
         return null;
     }
     if (!isset($latitude) or !isset($longitude)) {
         if ($uls = Places_Location::userStream()) {
             $latitude = $uls->getAttribute('latitude', null);
             $longitude = $uls->getAttribute('longitude', null);
             if (!isset($miles)) {
                 $miles = $uls->getAttribute('miles', 25);
             }
         } else {
             // put some defaults
             $latitude = 40.5806032;
             $longitude = -73.9755244;
             $miles = 25;
         }
     }
     $pa = null;
     if (Q_Config::get('Places', 'cache', 'autocomplete', true)) {
         $pa = new Places_Autocomplete();
         $pa->query = $input;
         $pa->types = $types ? implode(',', $types) : '';
         $pa->latitude = $latitude;
         $pa->longitude = $longitude;
         $pa->miles = $miles;
         if ($pa->retrieve()) {
             $ut = $pa->updatedTime;
             if (isset($ut)) {
                 $db = $pa->db();
                 $ut = $db->fromDateTime($ut);
                 $ct = $db->getCurrentTimestamp();
                 $cd = Q_Config::get('Places', 'cache', 'duration', 60 * 60 * 24 * 30);
                 if ($ct - $ut < $cd) {
                     // there are cached autocomplete results that are still viable
                     return Q::json_decode($pa->results, true);
                 }
             }
         }
     }
     $key = Q_Config::expect('Places', 'google', 'keys', 'server');
     $location = "{$latitude},{$longitude}";
     $radius = ceil(1609.34 * $miles);
     if ($types === null) {
         unset($types);
     }
     $query = http_build_query(compact('key', 'input', 'types', 'location', 'radius'));
     $url = "https://maps.googleapis.com/maps/api/place/autocomplete/json?{$query}";
     $ch = curl_init();
     curl_setopt($ch, CURLOPT_URL, $url);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     $json = curl_exec($ch);
     curl_close($ch);
     $response = json_decode($json, true);
     if (empty($response['predictions'])) {
         throw new Q_Exception("Places::autocomplete: Couldn't obtain predictions for {$input}");
     }
     if (!empty($response['error_message'])) {
         throw new Q_Exception("Places::autocomplete: " . $response['error_message']);
     }
     $results = $response['predictions'];
     if ($pa) {
         $pa->results = json_encode($results);
         $pa->save();
     }
     return $results;
 }
Exemple #6
0
 /**
  * @method decode
  * @static
  * @protected
  * @param {string} $tail This can either be JSON, or something that looks like a=b c=d where a, b, c, d are urlencoded
  * @return {array}
  */
 protected static function decode($tail)
 {
     if ($tail[0] === '{' and $result = Q::json_decode($tail, true)) {
         return $result;
     }
     $clauses = explode(' ', $tail);
     $result = array();
     foreach ($clauses as $clause) {
         list($left, $right) = explode('=', $clause);
         $right_parts = explode('/', $right);
         if (count($right_parts) === 1) {
             $result[urldecode($left)] = urldecode($right);
         } else {
             $left_parts = array();
             foreach ($right_parts as $rp) {
                 $left_parts[] = urldecode($rp);
             }
             $result[urldecode($left)] = $left_parts;
         }
     }
     return $result;
 }
Exemple #7
0
 /**
  * Download an image from pixabay
  * @param {string} $keywords Specify some string to search images on pixabay
  * @param {array} [$options=array()] Any additional options for pixabay api as per its documentation
  * @param {boolean} [$returnFirstImage=false] If true, downloads and returns the first image as data
  * @return {string} JSON according to pixabay api documentation
  */
 static function pixabay($keywords, $options = array(), $returnFirstImage = false)
 {
     $info = Q_Config::get('Q', 'images', 'pixabay', null);
     if (!$info['username']) {
         throw new Q_Exception_MissingConfig(array('fieldpath' => 'Q/images/pixabay/username'));
     }
     if (!$info['key']) {
         throw new Q_Exception_MissingConfig(array('fieldpath' => 'Q/images/pixabay/key'));
     }
     $username = $info['username'];
     $key = $info['key'];
     $defaults = array();
     $options = array_merge($defaults, $options);
     $optionString = http_build_query($options, '', '&');
     $keywords = urlencode(strtolower($keywords));
     $url = "http://pixabay.com/api/?username={$username}&key={$key}&q={$keywords}&{$optionString}";
     $json = @file_get_contents($url);
     $data = Q::json_decode($json, true);
     if (!$returnFirstImage) {
         return $data;
     }
     if (empty($data['hits'][0]['webformatURL'])) {
         return null;
     }
     $webformatUrl = $data['hits'][0]['webformatURL'];
     $data = @file_get_contents($webformatUrl);
     return $data;
 }
 /**
  * Get the names of the possible states
  * @method states
  * @static
  * @return {array}
  */
 static function states()
 {
     $column = Base_Streams_Participant::column_state();
     return Q::json_decode(str_replace("'", '"', '[' . $column[0][1] . ']'));
 }
Exemple #9
0
 /**
  * Subscribe to one or more streams, to start receiving notifications.
  * Posts "Streams/subscribe" message to the streams.
  * Also posts "Streams/subscribed" messages to user's "Streams/participating" stream.
  *	If options are not given check the subscription templates:
  *	1. generic publisher id and generic user
  *	2. exact publisher id and generic user
  *	3. generic publisher id and exact user
  *	default is to subscribe to ALL messages.
  *	If options are supplied - skip templates and use options.
  * Using subscribe if subscription is already active will modify existing
  * subscription - change type(s) or modify notifications
  * @method subscribe
  * @static
  * @param {string} $asUserId The id of the user that is joining. Pass null here to use the logged-in user's id.
  * @param {string} $publisherId The id of the user publishing all the streams
  * @param {array} $streams An array of Streams_Stream objects or stream names
  * @param {array} [$options=array()]
  * @param {array} [$options.filter] optional array with two keys
  * @param {array} [$options.filter.types] array of message types, if this is empty then subscribes to all types
  * @param {array} [$options.filter.notifications=0] limit number of notifications, 0 means no limit
  * @param {datetime} [$options.untilTime=null] time limit, if any for subscription
  * @param {array} [$options.rule=array()] optionally override the rule for new subscriptions
  * @param {array} [$options.rule.deliver=array('to'=>'default')] under "to" key,
  *   named the field under Streams/rules/deliver config, which will contain the names of destinations,
  *   which can include "email", "mobile", "email+pending", "mobile+pending"
  * @param {datetime} [$options.rule.readyTime] time from which user is ready to receive notifications again
  * @param {array} [$options.rule.filter] optionally set a filter for the rules to add
  * @param {boolean} [$options.skipRules] if true, do not attempt to create rules for new subscriptions
  * @param {boolean} [$options.skipAccess] if true, skip access check for whether user can join and subscribe
  * @return {array} An array of Streams_Participant rows from the database.
  */
 static function subscribe($asUserId, $publisherId, $streams, $options = array())
 {
     $streams2 = self::_getStreams($asUserId, $publisherId, $streams);
     $streamNames = array();
     foreach ($streams2 as $s) {
         $streamNames[] = $s->name;
     }
     if (empty($options['skipAccess'])) {
         self::_accessExceptions($streams2, $streamNames, 'join');
     }
     $participants = Streams::join($asUserId, $publisherId, $streams2, array('subscribed' => true, 'noVisit' => true, 'skipAccess' => Q::ifset($options, 'skipAccess', false)));
     $shouldUpdate = false;
     if (isset($options['filter'])) {
         $filter = Q::json_encode($options['filter']);
         $shouldUpdate = true;
     }
     $db = Streams_Subscription::db();
     if (isset($options['untilTime'])) {
         $untilTime = $db->toDateTime($options['untilTime']);
         $shouldUpdate = true;
     }
     $subscriptions = array();
     $rows = Streams_Subscription::select('*')->where(array('publisherId' => $publisherId, 'streamName' => $streamNames, 'ofUserId' => $asUserId))->fetchAll(PDO::FETCH_ASSOC);
     foreach ($rows as $row) {
         $sn = $row['streamName'];
         $subscriptions[$sn] = $row;
     }
     $messages = array();
     $pMessages = array();
     $streamNamesMissing = array();
     $streamNamesUpdate = array();
     foreach ($streamNames as $sn) {
         $messages[$publisherId][$sn] = array('type' => 'Streams/subscribe');
         $pMessages[] = array('type' => 'Streams/subscribed', 'instructions' => array('publisherId' => $publisherId, 'streamName' => $sn));
         if (empty($subscriptions[$sn])) {
             $streamNamesMissing[] = $sn;
             continue;
         }
         if ($shouldUpdate) {
             $streamNamesUpdate[] = $sn;
         }
     }
     if ($streamNamesUpdate) {
         Streams_Subscription::update()->set(compact('filter', 'untilTime'))->where(array('publisherId' => $publisherId, 'streamName' => $streamNamesUpdate, 'ofUserId' => $asUserId))->execute();
     }
     $rules = array();
     if ($streamNamesMissing) {
         $types = array();
         foreach ($streamNamesMissing as $sn) {
             $stream = $streams2[$sn];
             $types[$stream->type][] = $sn;
         }
         $subscriptionRows = array();
         $ruleRows = array();
         foreach ($types as $type => $sns) {
             // insert subscriptions
             if (!isset($filter) or !isset($untilTime)) {
                 $templates = Streams_Subscription::select('*')->where(array('publisherId' => array('', $publisherId), 'streamName' => $type . '/', 'ofUserId' => array('', $asUserId)))->fetchAll(PDO::FETCH_ASSOC);
                 $template = null;
                 foreach ($templates as $t) {
                     if (!$template or $template['publisherId'] == '' and $t['publisherId'] !== '' or $template['userId'] == '' and $t['userId'] !== '') {
                         $template = $t;
                     }
                 }
             }
             if (!isset($filter)) {
                 $filter = Q::json_encode($template ? Q::json_decode($template['filter']) : Streams_Stream::getConfigField($type, array('subscriptions', 'filter'), array("types" => array("^(?!(Users/)|(Streams/)).*/", "Streams/relatedTo", "Streams/chat/message"), "notifications" => 0)));
             }
             if (!isset($untilTime)) {
                 $untilTime = ($template and $template['duration'] > 0) ? new Db_Expression("CURRENT_TIMESTAMP + INTERVAL {$template['duration']} SECOND") : null;
             }
             foreach ($sns as $sn) {
                 $subscriptions[$sn] = $subscriptionRows[] = new Streams_Subscription(array('publisherId' => $publisherId, 'streamName' => $sn, 'ofUserId' => $asUserId, 'untilTime' => $untilTime, 'filter' => $filter));
             }
             if (!empty($options['skipRules'])) {
                 continue;
             }
             // insert up to one rule per subscription
             $rule = null;
             if (isset($options['rule'])) {
                 $rule = $options['rule'];
                 if (isset($rule['readyTime'])) {
                     $rule['readyTime'] = $db->toDateTime($rule['readyTime']);
                 }
                 if (isset($rule['filter']) and is_array($rule['filter'])) {
                     $rule['filter'] = Q::json_encode($rule['filter']);
                 }
                 if (isset($rule['deliver']) and is_array($rule['deliver'])) {
                     $rule['deliver'] = Q::json_encode($rule['deliver']);
                 }
             }
             if (!isset($rule)) {
                 $templates = Streams_Rule::select('*')->where(array('ofUserId' => array('', $asUserId), 'publisherId' => array('', $publisherId), 'streamName' => $type . '/', 'ordinal' => 1))->fetchAll(PDO::FETCH_ASSOC);
                 foreach ($templates as $t) {
                     if (!$rule or $rule['userId'] == '' and $t['userId'] !== '' or $rule['publisherId'] == '' and $t['publisherId'] !== '') {
                         $rule = $t;
                     }
                 }
             }
             if (!isset($rule)) {
                 $rule = array('deliver' => '{"to": "default"}', 'filter' => '{"types": [], "labels": []}');
             }
             if ($rule) {
                 $rule['ofUserId'] = $asUserId;
                 $rule['publisherId'] = $publisherId;
                 if (empty($rule['readyTime'])) {
                     $rule['readyTime'] = new Db_Expression("CURRENT_TIMESTAMP");
                 }
                 foreach ($sns as $sn) {
                     $row = $rule;
                     $row['streamName'] = $sn;
                     $row['ordinal'] = 1;
                     $row['filter'] = '';
                     $rules[$sn] = $ruleRows[] = $row;
                     $messages[$publisherId][$sn]['instructions'] = Q::json_encode(array('rule' => $row));
                 }
             }
         }
         Streams_Subscription::insertManyAndExecute($subscriptionRows);
         Streams_Rule::insertManyAndExecute($ruleRows);
     }
     foreach ($streamNames as $sn) {
         $subscription = $subscriptions[$sn];
         $stream = $streams2[$sn];
         // skip error testing for rule save BUT inform node.
         // Node can notify user to check the rules
         Q_Utils::sendToNode(array("Q/method" => "Streams/Stream/subscribe", "subscription" => Q::json_encode($subscription), "stream" => Q::json_encode($stream->toArray()), "rule" => isset($rules[$sn]) ? Q::json_encode($rules[$sn]) : null));
     }
     Streams_Message::postMessages($asUserId, $messages, true);
     Streams_Message::postMessages($asUserId, array($asUserId => array('Streams/participating' => $pMessages)), true);
     return $participants;
 }
Exemple #10
0
 /**
  * Method is called before setting the field and verifies that, if it is a string,
  * it contains a JSON array.
  * @method beforeSet_permissions
  * @param {string} $value
  * @return {array} An array of field name and value
  * @throws {Exception} An exception is thrown if $value is not string or is exceedingly long
  */
 function beforeSet_permissions($value)
 {
     if (is_string($value)) {
         $decoded = Q::json_decode($value, true);
         if (!is_array($decoded) or Q::isAssociative($decoded)) {
             throw new Q_Exception_WrongValue(array('field' => 'permissions', 'range' => 'JSON array'));
         }
     }
     return parent::beforeSet_permissions($value);
 }
Exemple #11
0
 /**
  * Loads data from JSON found in a file
  * @method load
  * @param {string} $filename The filename of the file to load.
  * @param {boolean} $ignoreCache=false
  *  Defaults to false. If true, then this function ignores
  *  the cached value, if any, and attempts to search
  *  for the file. It will cache the new value.
  * @return {boolean} Returns true if loaded, otherwise false.
  * @throws {Q_Exception_InvalidInput}
  */
 function load($filename, $ignoreCache = false)
 {
     $filename2 = Q::realPath($filename, $ignoreCache);
     if (!$filename2) {
         return false;
     }
     $this->filename = $filename2;
     // if class cache is set - use it
     if (isset(self::$cache[$filename2])) {
         $this->merge(self::$cache[$filename2]);
         return true;
     }
     // check Q_Cache and if set - use it
     // update class cache as it is not set
     $arr = Q_Cache::get("Q_Tree\t{$filename2}");
     if (isset($arr)) {
         self::$cache[$filename2] = $arr;
         $this->merge($arr);
         return true;
     }
     /**
      * @event Q/tree/load {before}
      * @param {string} filename
      * @return {array}
      */
     $arr = Q::event('Q/tree/load', compact('filename'), 'before');
     if (!isset($arr)) {
         try {
             // get file contents, remove comments and parse
             $json = file_get_contents($filename2);
             $json = preg_replace('/\\s*(?!<\\")\\/\\*[^\\*]+\\*\\/(?!\\")\\s*/', '', $json);
             $arr = Q::json_decode($json, true);
         } catch (Exception $e) {
             $arr = null;
         }
     }
     if (!isset($arr)) {
         throw new Q_Exception_InvalidInput(array('source' => $filename));
     }
     if (!is_array($arr)) {
         return false;
     }
     // $arr was loaded from $filename2 or by Q/tree/load before event
     $this->merge($arr);
     self::$cache[$filename2] = $arr;
     Q_Cache::set("Q_Tree\t{$filename2}", $arr);
     // no need to check result - on failure Q_Cache is disabled
     return true;
 }
function Assets_after_Assets_charge($params)
{
    $user = $payments = $amount = $currency = $charge = $adapter = $options = null;
    extract($params, EXTR_OVERWRITE);
    $description = 'a product or service';
    $stream = Q::ifset($options, 'stream', null);
    if ($stream) {
        $publisherId = $stream->publisherId;
        $publisher = Users_User::fetch($publisherId, true);
        if ($stream->type === 'Assets/subscription') {
            $plan = Streams::fetchOne($stream->getAttribute('planPublisherId'), $stream->getAttribute('planPublisherId'), $stream->getAttribute('planStreamName'), true);
            $months = $stream->getAttribute('months');
            $startDate = $stream->getAttribute('startDate');
            $endDate = $stream->getAttribute('endDate');
        }
        $description = $stream->title;
    } else {
        $publisherId = Users::communityId();
        $publisher = Users_User::fetch($publisherId, true);
    }
    if (isset($options['description'])) {
        $description = $options['description'];
    }
    $currencies = Q::json_decode(file_get_contents(ASSETS_PLUGIN_CONFIG_DIR . DS . 'currencies.json'), true);
    if (!isset($currencies['symbols'][$currency])) {
        throw new Q_Exception_BadValue(array('internal' => 'currency', 'problem' => 'no symbol found'), 'currency');
    }
    if (!isset($currencies['names'][$currency])) {
        throw new Q_Exception_BadValue(array('internal' => 'currency', 'problem' => 'no name found'), 'currency');
    }
    $symbol = $currencies['symbols'][$currency];
    $currencyName = $currencies['names'][$currency];
    $communityId = Users::communityId();
    $communityName = Users::communityName();
    $communitySuffix = Users::communitySuffix();
    $link = Q_Request::baseUrl('action.php') . "/Assets/payment?publisherId={$publisherId}&userId=" . $user->id;
    $fields = compact('user', 'publisher', 'publisherId', 'communityId', 'communityName', 'communitySuffix', 'description', 'subscription', 'stream', 'plan', 'currency', 'name', 'symbol', 'currencyName', 'amount', 'months', 'startDate', 'endDate', 'link');
    if ($user->emailAddress) {
        $email = new Users_Email();
        $email->address = $user->emailAddress;
        $email->retrieve(true);
        $emailSubject = Q_Config::get('Assets', 'transactional', 'charged', 'subject', false);
        $emailView = Q_Config::get('Assets', 'transactional', 'charged', 'body', false);
        if ($emailSubject !== false and $emailView) {
            $email->sendMessage($emailSubject, $emailView, $fields);
        }
    } else {
        if ($user->mobileNumber) {
            $mobile = new Users_Mobile();
            $mobile->number = $user->mobileNumber;
            $mobile->retrieve(true);
            if ($mobileView = Q_Config::get('Assets', 'transactional', 'charged', 'sms', false)) {
                $mobile->sendMessage($mobileView, $fields);
            }
        }
    }
    if ($publisher->emailAddress) {
        $email = new Users_Email();
        $email->address = $publisher->emailAddress;
        $email->retrieve(true);
        $emailSubject = Q_Config::get('Assets', 'transactional', 'charge', 'subject', false);
        $emailView = Q_Config::get('Assets', 'transactional', 'charge', 'body', false);
        if ($emailSubject !== false and $emailView) {
            $email->sendMessage($emailSubject, $emailView, $fields);
        }
    } else {
        if ($publisher->mobileNumber) {
            $mobile = new Users_Mobile();
            $mobile->number = $publisher->mobileNumber;
            $mobile->retrieve(true);
            if ($mobileView = Q_Config::get('Assets', 'transactional', 'charge', 'sms', false)) {
                $mobile->sendMessage($mobileView, $fields);
            }
        }
    }
}