Esempio n. 1
0
 /**
  * Post a Tweet with link to this
  * question
  */
 protected function tweet()
 {
     try {
         $reward = \Lampcms\Points::SHARED_CONTENT;
         $User = $this->Registry->Viewer;
         $oTweet = new Tweet();
         $oBitly = new Bitly($this->Registry->Ini->getSection('BITLY'));
         $oTwitter = new Twitter($this->Registry);
         $Resource = $this->obj;
         $Mongo = $this->Registry->Mongo;
         d('cp');
     } catch (\Exception $e) {
         d('Unable to post tweet because of this exception: ' . $e->getMessage() . ' in file: ' . $e->getFile() . ' on line: ' . $e->getLine());
         return;
     }
     $func = function () use($oTweet, $oBitly, $oTwitter, $Resource, $User, $reward, $Mongo) {
         $result = $oTweet->post($oTwitter, $oBitly, $Resource);
         if (!empty($result) && is_array($result)) {
             /**
              * If status is OK (Tweet was posted)
              * then reward the user with points!
              */
             if (!empty($result['id_str']) && '200' == $result['http_code']) {
                 $User->setReputation($reward);
                 /**
                  * Now need to also record Tweet Status data
                  * to TWEETS collection
                  */
                 try {
                     $coll = $Mongo->TWEETS;
                     $coll->ensureIndex(array('i_uid' => 1));
                     $tw_uid = !empty($result['user']) && !empty($result['user']['id_str']) ? $result['user']['id_str'] : null;
                     $tw_username = !empty($result['user']) && !empty($result['user']['screen_name']) ? $result['user']['screen_name'] : null;
                     /**
                      * Record Tweet status to TWEETS collection.
                      * Later can query Twitter to find
                      * replies to these Tweets and add them
                      * as "comments" to this Question or Answer
                      *
                      * HINT: if i_rid !== i_qid then it's an ANSWER
                      * if these are the same then it's a Question
                      * @var array
                      */
                     $aData = array('_id' => $result['id_str'], 'i_uid' => $User->getUid(), 'i_rid' => $Resource->getResourceId(), 'i_qid' => $Resource->getQuestionId(), 'tw_user_id_str' => $tw_uid, 'tw_username' => $tw_username, 'i_ts' => time(), 'h_ts' => date('r'));
                     $coll->save($aData);
                 } catch (\Exception $e) {
                     if (function_exists('e')) {
                         e('Unable to save data to TWEETS collection because of ' . $e->getMessage() . ' in file: ' . $e->getFile() . ' on line: ' . $e->getLine());
                     }
                 }
             }
         }
     };
     d('cp');
     \Lampcms\runLater($func);
 }
Esempio n. 2
0
 /**
  * Post to blogger blog
  *
  */
 protected function post()
 {
     d('cp');
     try {
         d('cp');
         $oBlogger = new ApiClient($this->Registry);
         d('cp');
         $User = $this->Registry->Viewer;
         d('cp');
         if (false === $oBlogger->setUser($User)) {
             d('User does not have Blogger Oauth credentials');
             return;
         }
         d('cp');
         $reward = $this->Registry->Ini->POINTS->SHARED_CONTENT;
         $Resource = $this->obj;
         d('cp');
         $oAdapter = new BloggerPostAdapter($this->Registry);
         d('cp');
     } catch (\Exception $e) {
         d('Unable to post to blogger because of this exception: ' . $e->getMessage() . ' in file: ' . $e->getFile() . ' on line: ' . $e->getLine());
         return;
     }
     d('cp');
     $func = function () use($oBlogger, $oAdapter, $Resource, $User, $reward) {
         $result = null;
         try {
             $result = $oBlogger->add($oAdapter->makeEntry($Resource));
         } catch (\Exception $e) {
             return;
         }
         if (!empty($result) && is_numeric($result)) {
             $User->setReputation($reward);
             /**
              * Also save blogger post id to QUESTIONS or ANSWERS
              * collection.
              * This way later on (maybe way later...)
              * We can add a function so that if user edits
              * Post on the site we can also edit it
              * on blogger via API
              * Can also delete from blogger if Resource
              * id deleted
              *
              */
             $Resource['blogger_id'] = $result;
             $Resource->save();
         }
     };
     //$func();
     \Lampcms\runLater($func);
 }
 /**
  * Update ONLINE_USERS collection
  * @todo exit if useragent is of known Crawler
  * 
  * @todo make logging guests online configurable option via Ini
  *
  */
 protected function run()
 {
     $Viewer = $this->Registry->Viewer;
     $ip = Request::getIP();
     $uid = $Viewer->getUid();
     d('uid: ' . $uid);
     $aData = array('ip' => $ip, 'i_ts' => time(), 'ua' => Request::getUserAgent(), 'action' => 'request_' . $this->Registry->Request->get('a', 's', 'home'), 'uri' => $_SERVER['REQUEST_URI'], 'title' => $this->title, 'category' => $this->category, 'a_kw' => !empty($this->aInfo['keywords']) ? explode(', ', $this->aInfo['keywords']) : array());
     if ($uid > 0) {
         $aData['i_uid'] = $uid;
         $aData['username'] = $Viewer->getDisplayName();
         $aData['avtr'] = $Viewer->getAvatarSrc();
         $aData['profile'] = $Viewer->getProfileUrl();
         $aData['role'] = $Viewer->getRoleId();
         $aData['i_pp'] = $Viewer->getProfitPoint();
     }
     $Mongo = $this->Registry->Mongo->getDb();
     $Geo = $this->Registry->Geo;
     $func = function () use($aData, $Mongo, $Geo) {
         $aGeo = $Geo->getLocation($aData['ip'])->toArray();
         $aData = $aData + $aGeo;
         /**
          * Need unique index uid
          *
          */
         if (array_key_exists('i_uid', $aData)) {
             $coll = $Mongo->ONLINE;
             $coll->ensureIndex(array('i_uid' => 1), array('unique' => true));
             $coll->ensureIndex(array('i_ts' => 1));
             $coll->update(array('i_uid' => $aData['i_uid']), $aData, array('upsert' => true));
         } else {
             /**
              * For guests the value of ip2long (int)
              * will be used as uid
              */
             $aData['i_uid'] = ip2long($aData['ip']);
             $coll = $Mongo->GUESTS;
             $coll->ensureIndex(array('i_uid' => 1), array('unique' => true));
             $coll->ensureIndex(array('i_ts' => 1));
             $coll->update(array('ip' => $aData['ip']), $aData, array('upsert' => true));
         }
         /**
          * Remove old records
          * Cleanup runs 10% of requests
          * removes records older than 24 hours
          */
         if (1 === rand(0, 10)) {
             $offset = time() - 60 * 60 * 24;
             $coll->remove(array('i_ts' => array('$lt' => $offset)));
         }
     };
     \Lampcms\runLater($func);
 }
Esempio n. 4
0
 /**
  * Post to Tumblr blog
  *
  */
 protected function post()
 {
     d('begin post to Tumblr');
     try {
         $oTumblr = new ApiClient($this->Registry);
         $User = $this->Registry->Viewer;
         if (false === $oTumblr->setUser($User)) {
             d('User does not have Tumblr Oauth credentials');
             return;
         }
         $reward = $this->Registry->Ini->POINTS->SHARED_CONTENT;
         $Resource = $this->obj;
         d('cp');
         $oAdapter = new TumblrPostAdapter($this->Registry);
         d('cp');
     } catch (\Exception $e) {
         d('Unable to post to Tumblr because of this exception: ' . $e->getMessage() . ' in file: ' . $e->getFile() . ' on line: ' . $e->getLine());
         return;
     }
     $func = function () use($oTumblr, $oAdapter, $Resource, $User, $reward) {
         $result = null;
         try {
             $result = $oTumblr->add($oAdapter->get($Resource));
         } catch (\Exception $e) {
             if (function_exists('d')) {
                 d('Unable to post to Tumblr: ' . $e->getMessage());
             }
             return;
         }
         if (!empty($result) && is_numeric($result)) {
             $User->setReputation($reward);
             /**
              * Also save Tumblr status id to QUESTIONS or ANSWERS
              * collection.
              * This way later on (maybe way later...)
              * We can add a function so that if user edits
              * Post on the site we can also edit it
              * on Tumblr via API
              * Can also delete from Tumblr if Resource
              * id deleted
              *
              */
             $Resource['i_tumblr'] = (int) $result;
             $Resource->save();
         }
     };
     \Lampcms\runLater($func);
 }
 /**
  * Notify all who follows the question
  * But exclude the Viewer - whoever just added
  * the new answer or whatever
  *
  *
  * and exclude all who follows the Viewer because all who
  * follows the Viewer will be notified via
  * the nofityUserFollowers
  *
  * @param int qid id of question
  *
  * @param int excludeUid UserID of user that should NOT
  *            be notified. Usually this is in a special case of when
  *            the answer or comment owner has already been notified
  *            so now we just have to exclude the same user in case same user
  *            is also the question author.
  *
  * @return object $this
  */
 protected function notifyQuestionFollowers($qid = null, $excludeUid = 0)
 {
     $viewerID = $this->Registry->Viewer->getUid();
     d('$viewerID: ' . $viewerID);
     $routerCallback = $this->Registry->Router->getCallback();
     /**
      * $qid can be passed here
      * OR in can be extracted from $this->Question
      */
     if ($qid) {
         $Question = new \Lampcms\Question($this->Registry);
         try {
             $Question->by_id((int) $qid);
         } catch (\Exception $e) {
             e('Unable to create Question by _id. Exception: ' . $e->getMessage() . ' in file: ' . $e->getFile() . ' on line: ' . $e->getLine());
             $Question = null;
         }
     } else {
         $Question = $this->Question;
     }
     if (null === $Question) {
         d('no $Question');
         return $this;
     }
     $subj = 'onNewAnswer' === $this->eventName || 'onApprovedAnswer' === $this->eventName ? 'email.subject.question_answer' : 'email.subject.question_comment';
     $body = 'onNewAnswer' === $this->eventName || 'onApprovedAnswer' === $this->eventName ? 'email.body.question_answer' : 'email.body.question_comment';
     $siteUrl = $this->Registry->Ini->SITE_URL;
     $updateType = 'onNewAnswer' === $this->eventName || 'onApprovedAnswer' === $this->eventName ? 'answer' : 'comment';
     $username = '******' === $this->eventName || 'onApprovedAnswer' === $this->eventName ? $this->obj['username'] : $this->aInfo['username'];
     if ('onNewAnswer' === $this->eventName || 'onApprovedAnswer' === $this->eventName) {
         $url = $this->obj->getUrl();
     } else {
         $url = $siteUrl . '{_WEB_ROOT_}/{_viewquestion_}/{_QID_PREFIX_}' . $this->aInfo['i_qid'] . '/#c' . $this->aInfo['_id'];
         $url = $routerCallback($url);
     }
     d('url: ' . $url);
     $content = 'onNewAnswer' !== $this->eventName ? "\n____\n" . \strip_tags($this->aInfo['b']) . "\n" : '';
     $varsBody = array('{username}' => $username, '{title}' => $this->Question['title'], '{body}' => $content, '{link}' => $url, '{site_title}' => $this->Registry->Ini->SITE_NAME, '{home}' => $this->Registry->Router->getHomePageUrl());
     $body = new TranslatableBody($body, $varsBody);
     $subj = new TranslatableSubject($subj);
     $Mailer = $this->Registry->Mailer;
     $Mailer->setCache($this->Registry->Cache);
     /**
      * MongoCollection USERS
      *
      * @var object MongoCollection
      */
     $coll = $this->collUsers;
     d('before shutdown function for question followers');
     /**
      * Get array of followers for this question
      */
     $aFollowers = $Question['a_flwrs'];
     if (!empty($aFollowers)) {
         $func = function () use($updateType, $viewerID, $aFollowers, $subj, $body, $coll, $Mailer, $excludeUid) {
             /**
              * Remove $viewerID from aFollowers
              * Remove excludeID from aFollowers
              * Removing these userIDs from
              * the find $in condition is guaranteed to not
              * have these IDs in result and is much better
              * than adding extra $ne or $nin conditions
              * on these uids to find()
              *
              */
             if (false !== ($key = array_search($viewerID, $aFollowers))) {
                 array_splice($aFollowers, $key, 1);
             }
             if (!empty($excludeUid)) {
                 if (false !== ($key = array_search($excludeUid, $aFollowers))) {
                     array_splice($aFollowers, $key, 1);
                 }
             }
             array_unique($aFollowers);
             /**
              * Find all users who follow this question
              * and
              * are not also following the Viewer
              *
              * In case of comment we should not exclude
              * Viewer followers because Viewer followers are NOT
              * notified on user comment
              *
              */
             if ('comment' !== $updateType) {
                 /**
                  * Condition: Find all users with _id in array of $aFollowers
                  * AND NOT FOLLOWING viewer (who is the author of this answer)
                  * because they will also be notified of this answer
                  * in a separate email that is sent to all followers of Viewer
                  */
                 $cur = $coll->find(array('_id' => array('$in' => $aFollowers), 'a_f_u' => array('$nin' => array(0 => $viewerID)), 'ne_fq' => array('$ne' => true)), array('email' => true, 'locale' => true));
             } else {
                 $cur = $coll->find(array('_id' => array('$in' => $aFollowers), 'ne_fq' => array('$ne' => true)), array('email' => true, 'locale' => true));
             }
             $count = $cur->count();
             if ($count > 0) {
                 $Mailer->mailFromCursor($cur, $subj, $body);
             }
         };
         \Lampcms\runLater($func);
     }
     return $this;
 }
Esempio n. 6
0
 protected function post()
 {
     $url = $this->obj->getUrl();
     $label = $this->obj->getTitle();
     $comment = 'I asked this on ' . $this->Registry->Ini->SITE_NAME;
     if ($this->obj instanceof \Lampcms\Answer) {
         $comment = 'My answer to "' . $label . '"';
     }
     d('$comment: ' . $comment . ' label: ' . $label . ' $url: ' . $url);
     $reward = \Lampcms\Points::SHARED_CONTENT;
     $User = $this->Registry->Viewer;
     $token = $User->getLinkedinToken();
     $secret = $User->getlinkedinSecret();
     try {
         $oLI = new ApiClient($this->aConfig['OAUTH_KEY'], $this->aConfig['OAUTH_SECRET']);
         $oLI->setUserToken($token, $secret);
     } catch (\Exception $e) {
         e('Error during setup of Linkedin ApiClient object ' . $e->getMessage() . ' in ' . $e->getFile() . ' on ' . $e->getLine());
         return $this;
     }
     $func = function () use($oLI, $User, $comment, $label, $url, $reward) {
         try {
             $oLI->share($comment, $label, $url);
         } catch (\Exception $e) {
             return;
         }
         $User->setProfitPoint($reward);
     };
     \Lampcms\runLater($func);
 }
Esempio n. 7
0
 /**
  * Import user's contacts from Google account
  * We will be able to use contacts to match new users
  * with existing members they may already know
  *
  * @param int $uid _id of newly created user
  */
 protected function addContacts($uid)
 {
     if (\in_array('https://www.google.com/m8/feeds/', $this->scopes)) {
         $Curl = new \Lampcms\Curl();
         $ContactParser = new \Lampcms\Modules\Google\Contacts($this->Registry->Mongo, $Curl);
         $accessToken = $this->tokenObject->access_token;
         $func = function () use($ContactParser, $uid, $accessToken) {
             $ContactParser->import($uid, $accessToken);
         };
         \Lampcms\runLater($func);
     }
 }
 /**
  * Post a Link to this question or answer
  * To User's Facebook Wall
  *
  */
 protected function post()
 {
     try {
         $reward = \Lampcms\Points::SHARED_CONTENT;
         $User = $this->Registry->Viewer;
         $oFB = $this->Registry->Facebook;
         $Resource = $this->obj;
         $Mongo = $this->Registry->Mongo;
         $logo = !empty($this->aFB['SITE_LOGO']) ? $this->aFB['SITE_LOGO'] : null;
         /**
          * @todo Translate String(s) of caption
          * It appears on Facebook Wall under the link
          * @var string
          */
         $caption = $this->obj instanceof \Lampcms\Question ? 'Please click if you can answer this question' : 'I answered this question';
         $description = Utf8String::factory($this->obj['b'], 'utf-8', true)->asPlainText()->valueOf();
     } catch (\Exception $e) {
         d('Unable to post to facebook because of this exception: ' . $e->getMessage() . ' in file: ' . $e->getFile() . ' on line: ' . $e->getLine());
         return;
     }
     $func = function () use($oFB, $Resource, $User, $reward, $Mongo, $logo, $caption, $description) {
         $result = null;
         $aData = array('link' => $Resource->getUrl(), 'name' => $Resource['title'], 'message' => $caption, 'description' => $description);
         if (!empty($logo) && 'http' == substr($logo, 0, 4)) {
             $aData['picture'] = $logo;
         }
         try {
             $result = $oFB->postUpdate($User, $aData);
         } catch (\Exception $e) {
             // does not matter
         }
         if (!empty($result) && false !== ($decoded = json_decode($result, true))) {
             /**
              * If status is OK
              * then reward the user with points!
              */
             if (!empty($decoded['id'])) {
                 $status_id = (string) $decoded['id'];
                 $User->setProfitPoint($reward);
                 /**
                  * Now need to also record Facebook id
                  * to FB_STATUSES collection
                  */
                 try {
                     /**
                      * Also save fb_status to QUESTIONS or ANSWERS
                      * collection.
                      * This way later on (maybe way later...)
                      * We can add a function so that if user edits
                      * Post on the site we can also edit it
                      * on Tumblr via API
                      * 
                      */
                     $Resource['fb_status'] = $status_id;
                     $Resource->save();
                 } catch (\Exception $e) {
                     if (function_exists('e')) {
                         e('Unable to save data to FB_STATUSES collection because of ' . $e->getMessage() . ' in file: ' . $e->getFile() . ' on line: ' . $e->getLine());
                     }
                 }
             }
         }
     };
     \Lampcms\runLater($func);
 }
 /**
  * Notify all who follows the question
  * But exclude the Viewer - whoever just added
  * the new answer or whatever
  *
  *
  * and exclude all who follows the Viewer because all who
  * follows the Viewer will be notified via
  * the nofityUserFollowers
  *
  * @param int qid id of question
  *
  * @param int excludeUid UserID of user that should NOT
  * be notified. Usually this is in a special case of when
  * the answer or comment owner has already been notified
  * so now we just have to exclude the same user in case same user
  * is also the question author.
  *
  * @return object $this
  */
 protected function notifyQuestionFollowers($qid = null, $excludeUid = 0)
 {
     $viewerID = $this->Registry->Viewer->getUid();
     d('$viewerID: ' . $viewerID);
     /**
      *
      * $qid can be passed here
      * OR in can be extracted from $this->Question
      *
      */
     if ($qid) {
         $Question = new \Lampcms\Question($this->Registry);
         try {
             $Question->by_id((int) $qid);
         } catch (\Exception $e) {
             e($e->getMessage() . ' in file: ' . $e->getFile() . ' on line: ' . $e->getLine());
             $Question = null;
         }
     } else {
         $Question = $this->Question;
     }
     if (null === $Question) {
         return $this;
     }
     $updateType = 'onNewAnswer' === $this->eventName ? 'answer' : 'comment';
     $subj = sprintf(static::$QUESTION_FOLLOW_SUBJ, $updateType);
     d('cp');
     $siteUrl = $this->Registry->Ini->SITE_URL;
     $username = '******' === $updateType ? $this->obj['username'] : $this->aInfo['username'];
     $url = 'answer' === $updateType ? $this->obj->getUrl() : $siteUrl . '/q' . $this->aInfo['i_qid'] . '/#c' . $this->aInfo['_id'];
     d('url: ' . $url);
     $content = 'comment' === $updateType ? "\n____\n" . \strip_tags($this->aInfo['b']) . "\n" : '';
     $body = vsprintf(static::$QUESTION_FOLLOW_BODY, array($username, $updateType, $this->Question['title'], $url, $siteUrl, $content));
     d('$body: ' . $body);
     $oMailer = $this->Registry->Mailer;
     d('cp');
     /**
      * MongoCollection USERS
      * @var object MongoCollection
      */
     $coll = $this->collUsers;
     d('before shutdown function for question followers');
     /**
      * Get array of followers for this question
      */
     $aFollowers = $Question['a_flwrs'];
     if (!empty($aFollowers)) {
         $func = function () use($updateType, $viewerID, $aFollowers, $updateType, $subj, $body, $coll, $oMailer, $excludeUid) {
             /**
              * Remove $viewerID from aFollowers
              * Remove excludeID from aFollowers
              * Removing these userIDs from
              * the find $in condition is guaranteed to not
              * have these IDs in result and is much better
              * than adding extra $ne or $nin conditions
              * on these uids to find()
              *
              */
             if (false !== ($key = array_search($viewerID, $aFollowers))) {
                 array_splice($aFollowers, $key, 1);
             }
             if (!empty($excludeUid)) {
                 if (false !== ($key = array_search($excludeUid, $aFollowers))) {
                     array_splice($aFollowers, $key, 1);
                 }
             }
             array_unique($aFollowers);
             /**
              * Find all users who follow this question
              * and
              * are not themselves the viewer (a viewer may reply to
              * own question and we don't want to notify viewer of that)
              *
              * In case of comment we should not exclude
              * user followers because user followers are NOT
              * notified on user comment
              *
              */
             if ('comment' !== $updateType) {
                 $cur = $coll->find(array('_id' => array('$in' => $aFollowers), 'a_f_u' => array('$nin' => array(0 => $viewerID)), 'ne_fq' => array('$ne' => true)), array('email'));
             } else {
                 $cur = $coll->find(array('_id' => array('$in' => $aFollowers), 'ne_fq' => array('$ne' => true)), array('email'));
             }
             $count = $cur->count();
             if ($count > 0) {
                 /**
                  * Passing callback function
                  * to exclude mailing to those who
                  * opted out on Email On Followed Question
                  */
                 $oMailer->mailFromCursor($cur, $subj, $body);
                 /**
                 * , function($a){
                 if(!empty($a['email']) && (!array_key_exists('e_fq', $a) || false !== $a['e_fq'])){
                 return $a['email'];
                 }
                 
                 return null;
                 }
                 */
             }
         };
         \Lampcms\runLater($func);
     }
     return $this;
 }
Esempio n. 10
0
 /**
  * This is a main mail function to send
  * email to individual user or to array or recipients
  * or even by passing Iterator object to it such
  * as MongoCursor
  *
  * The better more fine-tuned method mailFromCursor
  * should be used when sending mass email and when we know
  * that cursor contains several hundreds of records
  *
  * Sends our emails using the mail()
  * but can be sent from inside the runLater
  * This way function returns immediately
  *
  * Also accept Iterator so we can use the
  * cursor in place of $to
  *
  * Has the ability to pass in
  * callback function and that function
  * would return email address or false
  * if email should not be sent
  * This will be used if $to is iterator or array
  * and contains fields like e_ft = null or does not exist
  * So we can check if (empty($a['e_ft']){
  *  return false // skip this one
  * } else {
  *  return $a['email'];
  * }
  *
  * @todo for best result we should actually fork another php
  *       script as regular cgi script (not fastcgi, just cgi php)
  *       and just pass arguments to it and let it run as long as necessary,
  *       looping over the array of recipients and sending out emails
  *       The problem is that we cannot just pass cursor or even an array
  *       of recipients to a cgi like this, we need to somehow pass data
  *       differently like not the actual data but the conditions and then
  *       let the cgi find that data and use it. We can do this via a cache
  *       just put array into cache and pass cache key to cgi script
  *       that would work for up to 4MB of data
  *       And then let cgi delete that key and just in case set the expiration
  *       on that key too so it will be deleted eventually even if cgi
  *       dies for some reason
  *
  * @param mixed    $to
  * @param string   $subject
  * @param string   $body
  *
  * @param bool     $sendLater if true (default) then will run
  *                            via the runLater, otherwise
  *                            will run immediately. So if this method itself is
  *                            invoked from some registered shutdown function then it
  *                            makes sense to not use the 'later' feature.
  *
  * @param function $func      callback function to be applied
  *                            to each record of the $to array.
  *
  * @return bool
  * @throws DevException
  */
 public function mail($to, $subject, $body = null, $func = null, $sendLater = true)
 {
     if (!is_string($to) && !is_array($to) && !is_callable($to) && (!is_object($to) || !$to instanceof \Iterator)) {
         $class = \is_object($to) ? \get_class($to) : 'not an object';
         throw new DevException('$to can be only string or array or object implementing Iterator. Was: ' . \gettype($to) . ' class: ' . $class);
     }
     if (null === $body && (!is_object($subject) || !$subject instanceof \Swift_Message)) {
         throw new DevException('$body cannot be null if $subject is not instance of \\Swift_Message');
     }
     if (\is_string($to)) {
         $aTo = array($to);
     } elseif (\is_array($to)) {
         $aTo = $to;
     } else {
         d('$to is callable function');
     }
     $fromEmail = $this->adminEmail;
     $fromName = $this->siteName;
     $Swift = $this->SwiftMailer;
     $Cache = $this->Cache;
     $callable = function () use($subject, $body, $fromEmail, $fromName, $aTo, $func, $Swift, $Cache) {
         $translatedMessages = array();
         $translators = array();
         if (!is_array($aTo) && is_callable($aTo)) {
             $aTo = $aTo();
         }
         $total = is_array($aTo) ? count($aTo) : $aTo->count();
         /**
          * @todo deal with breaking up
          *       the long array/cursor into
          *       smaller chunks and send emails
          *       in groups on N then wait N seconds
          *       This is handled differently for cursors and for arrays
          */
         if ($total > 0) {
             $failedRecipients = array();
             $numSent = 0;
             try {
                 $message = is_object($subject) && $subject instanceof \Swift_Message ? $subject : \Swift_Message::newInstance($subject)->setFrom(array($fromEmail => $fromName))->setBody($body)->setCharset('utf-8');
             } catch (\Exception $e) {
                 /**
                  * Do not use error-level logging because error log e($message)
                  * sends out email to admin.
                  * if we failed to send out email we don't want to attempt to notify
                  * admin by email - it can create infinite loop
                  */
                 d('Unable to create email message: ' . $e->getMessage() . ' Exception: ' . get_class($e));
                 return;
             }
             foreach ($aTo as $to) {
                 /**
                  * Deal with format of array when array
                  * is result of iterator_to_array($cur)
                  * where $cur is MongoCursor - result of
                  * find()
                  */
                 if (is_array($to)) {
                     /**
                      * If callback function is passed to mail()
                      * then it must accept array or
                      * one user record as argument and must
                      * return either email address (string)
                      * or false if record should be skipped
                      * For example, if array contains something like this
                      * 'email' => user@email.com,
                      * 'e_ft' => null
                      *
                      * Which indicates that user does not want
                      * to receive emails on followed tag
                      *
                      * This is a way to pass callback to serve
                      * as a filter - to users who opted out
                      * or receiving emails on specific events
                      * will not receive them
                      *
                      * Since each opt-out flag is different, the
                      * each callback for specific type of mailing
                      * will also be different.
                      *
                      */
                     if (is_callable($func)) {
                         $to = $func($to);
                     } elseif (!empty($to['email'])) {
                         $to = $to['email'];
                     }
                 }
                 /**
                  * Now it is possible that callback
                  * function returned null or false so we
                  * must now check that $to is not
                  * empty
                  * Also if array did not contain
                  * the 'email' key then nothing will
                  * be sent at this point because
                  * the $to will be !is_string() at
                  * this time - it will still be array
                  */
                 if (empty($to) || !is_string($to)) {
                     continue;
                 }
                 /**
                  * If user has locale and subject or body
                  * is Translatable then translate message
                  * and create locale-specific message object
                  *
                  */
                 $ER = error_reporting(0);
                 $message->setTo($to);
                 try {
                     $numSent += $Swift->send($message, $failedRecipients);
                 } catch (\Exception $e) {
                     /**
                      * Do not user error-level loggin because error log e($message)
                      * sends out email to admin.
                      * if we failed to send out email we don't want to attempt to notify
                      * admin by email - it can create infinite loop
                      */
                     d('Unable to send email: ' . $e->getMessage() . ' Exception: ' . get_class($e));
                 }
                 if (!empty($failedRecipients)) {
                     d('Failed recipients: ' . json_encode($failedRecipients));
                 }
                 error_reporting($ER);
             }
             d('sent ' . $numSent . ' emails');
         }
     };
     if ($sendLater) {
         \Lampcms\runLater($callable);
     } else {
         $callable();
     }
     return true;
 }
Esempio n. 11
0
 /**
  * This is a main mail function to send
  * email to individual user or to array or receipients
  * or even by passing Iterator object to it such
  * as MongoCursor
  *
  * The better more fine-tuned method mailFromCursor
  * should be used when sending mass email and when we know
  * that cursor contains several hundreds of records
  *
  * Sends our emails using the mail()
  * but can be sent from inside the runLater
  * This way function returns immediately
  *
  * Also accept Iteractor so we can use the
  * cursor in place of $to
  *
  * Has the ability to pass in
  * callback function and that function
  * would return email address or false
  * if email should not be sent
  * This will be used if $to is iterator or array
  * and contains fields like e_ft = null or does not exist
  * So we can check if (empty($a['e_ft']){
  *  return flase // skip this one
  * } else {
  *  return $a['email'];
  * }
  *
  *@todo for best result we should actually fork another php
  *script as regular cgi script (not fastcgi, just cgi php)
  *and just pass arguments to it and let it run as long as necessary,
  *looping over the array of recepients and sending out emails
  *The problem is that we cannot just pass cursor or even an array
  *of receipients to a cgi like this, we need to somehow pass data
  *differently like not the actual data but the conditions and then
  *let the cgi find that data and use it. We can do this via a cache
  *just put array into cache and pass cache key to cgi script
  *that would work for up to 4MB of data
  *And then let cgi delete that key and just in case set the expiration
  *on that key too so it will be deleted eventually even if cgi
  *dies for some reason
  *
  * @param mixed $to
  * @param string $subject
  * @param string $body
  *
  * @param bool $sendLater if true (default) then will run
  * via the runLater, otherwise
  * will run immediately. So if this method itself is
  * invoked from some registered shutdown function then it
  * makes sense to not use the 'later' feature.
  *
  * @param function $func callback function to be applied
  * to each record of the array.
  *
  * @throws DevException
  */
 public function mail($to, $subject, $body, $func = null, $sendLater = true)
 {
     if (!is_string($to) && !is_array($to) && (!is_object($to) || !$to instanceof \Iterator)) {
         $class = is_object($to) ? get_class($to) : 'not an object';
         throw new DevException('$to can be only string or array or object implementing Iterator. Was: ' . gettype($to) . ' class: ' . $class);
     }
     $aTo = is_string($to) ? (array) $to : $to;
     $aHeaders = array();
     $aHeaders['From'] = $this->from;
     $aHeaders['Reply-To'] = $this->adminEmail;
     $headers = \Lampcms\prepareHeaders($aHeaders);
     d('$subject: ' . $subject . ' body: ' . $body . ' headers: ' . $headers . ' $aTo: ' . print_r($aTo, 1));
     $callable = function () use($subject, $body, $headers, $aTo, $func) {
         $total = is_array($aTo) ? count($aTo) : $aTo->count();
         /**
          * @todo deal with breaking up
          * the long array/cursor into
          * smaller chunks and send emails
          * in groups on N then wait N seconds
          * This is handled differently for cursors and for arrays
          */
         if ($total > 0) {
             foreach ($aTo as $to) {
                 /**
                  * Deal with format of array when array
                  * is result of iterator_to_array($cur)
                  * where $cur is MongoCursor - result of
                  * find()
                  */
                 if (is_array($to)) {
                     /**
                      * If callback function is passed to mail()
                      * then it must accept array or
                      * one user record as argument and must
                      * return either email address (string)
                      * or false if record should be skipped
                      * For example, if array contains something like this
                      * 'email' => user@email.com,
                      * 'e_ft' => null
                      *
                      * Which indicates that user does not want
                      * to receive emails on followed tag
                      *
                      * This is a way to pass callback to serve
                      * as a filter - to users who opted out
                      * or receiving emails on specific events
                      * will not receive them
                      *
                      * Since each opt-out flag is different, the
                      * each callback for specific type of mailing
                      * will also be different.
                      *
                      */
                     if (is_callable($func)) {
                         $to = $func($to);
                     } elseif (!empty($to['email'])) {
                         $to = $to['email'];
                     }
                 }
                 /**
                  * Now it is possible that callback
                  * function returned null or false so we
                  * must now check that $to is not
                  * empty
                  * Also if array did not contain
                  * the 'email' key then nothing will
                  * be sent at this point because
                  * the $to will be !is_string() at
                  * this time - it will still be array
                  */
                 if (empty($to) || !is_string($to)) {
                     continue;
                 }
                 $ER = error_reporting(0);
                 if (true !== @\mail($to, $subject, $body, $headers)) {
                     // was unable to send out email
                     if (function_exists('e')) {
                         e('unable to send email to ' . $to . ' subject: ' . $subj . ' body: ' . $body);
                     }
                 }
                 error_reporting($ER);
             }
         }
     };
     if ($sendLater) {
         \Lampcms\runLater($callable);
     } else {
         $callable();
     }
     return true;
 }
Esempio n. 12
0
 protected function notifyModerators()
 {
     /**
      * Proceed ONLY when Question or Answer has
      * a PENDING status
      */
     d('need to notify moderators of pending item');
     $coll = $this->Registry->Mongo->USERS;
     $Mailer = $this->Registry->Mailer;
     $Mailer->setCache($this->Registry->Cache);
     if ('onNewPendingQuestion' == $this->eventName) {
         $subj = new TranslatableSubject('email.subject.new_question_moderation');
         $tpl = 'email.body.new_question_moderation';
         $vars = array('{username}' => $this->obj['username'], '{title}' => $this->obj['title'], '{body}' => $this->obj['intro'], '{link}' => $this->obj->getUrl());
         $body = new TranslatableBody($tpl, $vars);
     } else {
         $subj = new TranslatableSubject('email.subject.new_answer_moderation');
         $tpl = 'email.body.new_answer_moderation';
         $vars = array('{username}' => $this->obj['username'], '{title}' => $this->obj->getTitle(), '{body}' => \strip_tags($this->obj['b']), '{link}' => $this->obj->getUrl());
         $body = new TranslatableBody($tpl, $vars);
     }
     $func = function () use($subj, $body, $coll, $Mailer) {
         $cur = $coll->find(array('role' => array('$in' => array('moderator', 'administrator'))), array('email' => true, 'locale' => true));
         $count = $cur->count();
         if ($count > 0) {
             $Mailer->mailFromCursor($cur, $subj, $body);
         }
     };
     \Lampcms\runLater($func);
     return $this;
 }
Esempio n. 13
0
 /**
  * Update LOGIN_LOG collection
  *
  */
 protected function run()
 {
     $Viewer = $this->Registry->Viewer;
     if (!is_object($Viewer)) {
         d('Could not get Viewer object');
         return;
     }
     $ip = Request::getIP();
     $uid = $Viewer->getUid();
     d('uid: ' . $uid);
     if ($uid > 0) {
         $aData = array('ip' => $ip, 'i_uid' => $uid, 'i_ts' => time(), 'ua' => Request::getUserAgent(), 'login_method' => $this->loginMethod);
         $Mongo = $this->Registry->Mongo->getDb();
         //$Geo 	= $this->Registry->Geo;
         $func = function () use($aData, $Mongo) {
             //$aGeo = $Geo->getLocation($aData['ip'])->toArray();
             //$aData = $aData + $aGeo;
             $coll = $Mongo->LOGIN_LOG;
             $coll->ensureIndex(array('i_uid' => 1));
             $coll->ensureIndex(array('ip' => 1));
             $coll->insert($aData);
         };
         \Lampcms\runLater($func);
     }
 }