Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Service/Feed/Feeder.php
<?php

namespace XF\Service\Feed;

use
XF\Entity\Feed;
use
XF\Entity\Thread;

use function
count;

class
Feeder extends \XF\Service\AbstractService
{
   
/** @var Feed */
   
protected $feed;

    protected
$feedData;

    protected
$pendingEntries;

    public function
setupImport(Feed $feed, $haltOnError = false)
    {
       
$this->setFeed($feed);
       
$this->pendingEntries = null;

       
$reader = $this->getFeedReader();
       
$feedData = $reader->getFeedData();
        if (!
$feedData && empty($feedData['entries']))
        {
           
// we've tried to fetch the feed data and failed we should trigger an update
            // of the last_fetch date to ensure we don't end up infinitely trying to fetch
           
$this->updateLastFetch($feed);

            if (
$haltOnError)
            {
                throw new \
XF\PrintableException(\XF::phrase('there_was_problem_requesting_feed', [
                   
'message' => $reader->getException()
                        ?
$reader->getException()->getMessage()
                        : \
XF::phrase('n_a')
                ]));
            }

            return
null;
        }

       
$this->setFeedData($feedData);
       
$this->updateLastFetch($feed);

        return
$feedData;
    }

    protected function
updateLastFetch(\XF\Entity\Feed $feed, $time = null)
    {
       
$feed->last_fetch = $time ?: time();
       
$feed->save(false);
    }

    protected function
setFeed(Feed $feed)
    {
       
$this->feed = $feed;
    }

    protected function
setFeedData(array $feedData)
    {
       
$this->feedData = $feedData;
    }

    protected function
getPendingEntries()
    {
        if (
$this->pendingEntries === null)
        {
           
$feedData = $this->feedData;

           
$ids = [];
            foreach (
$feedData['entries'] AS $id => $entry)
            {
               
$uniqueEntryId = utf8_substr($entry['id'], 0, 250);
                if (isset(
$ids[$uniqueEntryId]))
                {
                    unset(
$feedData['entries'][$id]);
                    continue;
                }

               
$ids[$uniqueEntryId] = $id;
            }

           
$existingEntries = $this->app->finder('XF:FeedLog')
                ->
where('feed_id', $this->feed->feed_id)
                ->
where('unique_id', array_keys($ids))
                ->
keyedBy('unique_id')
                ->
fetch();

           
$this->pendingEntries = array_reverse(
               
array_filter($feedData['entries'], function($entry) use($existingEntries)
                {
                    return !isset(
$existingEntries[$entry['id']]);
                })
            );
        }

        return
$this->pendingEntries;
    }

    public function
countPendingEntries()
    {
        return
count($this->getPendingEntries());
    }

    public function
importEntries()
    {
       
$entries = $this->getPendingEntries();

        foreach (
$entries AS $entry)
        {
           
$this->importEntry($entry);
        }
    }

    public function
importEntry(array $entry)
    {
       
$actionUser = $this->getEntryActionUser($entry);

        return \
XF::asVisitor($actionUser, function() use ($entry)
        {
           
$creator = $this->setupThreadCreate($entry);
            if (!
$creator->validate($errors))
            {
               
$error = reset($errors);
               
$feedId = $this->feed->feed_id;
                \
XF::logException(new \Exception("Error posting feed entry $entry[id] for feed $feedId: $error"));
                return
false;
            }

           
$db = $this->db();
           
$db->beginTransaction();

           
$creator->save();
           
$this->logEntry($entry, $creator->getThread());

           
$db->commit();

           
$creator->sendNotifications();

            return
true;
        });
    }

    protected function
getEntryActionUser(array $entry)
    {
       
$feed = $this->feed;

        if (
$feed->user_id && $feed->User)
        {
            return
$feed->User;
        }

       
$userRepo = $this->repository('XF:User');
       
$strFormatter = $this->app->stringFormatter();

        if (!empty(
$entry['author']))
        {
            return
$userRepo->getGuestUser($strFormatter->wholeWordTrim($entry['author'], 50, 0, ''));
        }
        else
        {
            return
$userRepo->getGuestUser($strFormatter->wholeWordTrim($feed->title, 50, 0, ''));
        }
    }

   
/**
     * @return \XF\Service\Thread\Creator
     */
   
protected function setupThreadCreate(array $entry)
    {
       
$feed = $this->feed;

       
/** @var \XF\Service\Thread\Creator $creator */
       
$creator = $this->service('XF:Thread\Creator', $feed->Forum);

       
$creator->setIsAutomated();
       
$creator->setContent($feed->getEntryTitle($entry), $feed->getEntryMessage($entry));
       
$creator->setPrefix($feed->prefix_id);
       
$creator->setDiscussionState($feed->discussion_visible ? 'visible' : 'moderated');
       
$creator->setDiscussionOpen($feed->discussion_open);
       
$creator->setSticky($feed->discussion_sticky);

        return
$creator;
    }

    protected function
logEntry(array $entry, Thread $thread)
    {
       
$feed = $this->feed;

       
$log = $this->em()->create('XF:FeedLog');
       
$log->feed_id = $feed->feed_id;
       
$log->unique_id = utf8_substr($entry['id'], 0, 250);
       
$log->hash = md5($entry['id'] . $entry['title'] . $entry['content']);
       
$log->thread_id = $thread->thread_id;
       
$log->save(false, false);
    }

   
/**
     * @return Reader
     */
   
protected function getFeedReader()
    {
        return
$this->service('XF:Feed\Reader', $this->feed->url);
    }
}