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

namespace XF\Service;

class
Oembed extends AbstractService
{
    protected
$forceRefresh = false;
    protected
$maxConcurrent = 10;

   
/**
     * @var \XF\Repository\Oembed
     */
   
protected $oEmbedRepo;

    protected function
setup()
    {
       
$this->oEmbedRepo = $this->repository('XF:Oembed');
    }

    public function
forceRefresh($value = true)
    {
       
$this->forceRefresh = (bool)$value;
    }

    public function
isRefreshForced()
    {
        return
$this->forceRefresh;
    }

    public function
getOembed($mediaSiteId, $mediaId)
    {
       
$oEmbed = $this->oEmbedRepo->getOembed($mediaSiteId, $mediaId);
        if (
$oEmbed)
        {
            if (
$this->isRefreshRequired($oEmbed))
            {
               
$this->refetchOembed($oEmbed);
            }
        }
        else
        {
            if (
$this->canFetchOembed())
            {
               
$oEmbed = $this->fetchNewOembed($mediaSiteId, $mediaId);
            }
        }

        return
$oEmbed;
    }

    protected function
isRefreshRequired(\XF\Entity\Oembed $oEmbed)
    {
        if (
$this->forceRefresh)
        {
            return
true;
        }

        return
$oEmbed->isRefreshRequired() && $this->canFetchOembed();
    }

    protected function
canFetchOembed()
    {
        if (
$this->forceRefresh)
        {
            return
true;
        }

       
$active = $this->oEmbedRepo->getTotalActiveFetches();
        return (
$active < $this->maxConcurrent);
    }

    public function
fetchNewOembed($mediaSiteId, $mediaId)
    {
       
/** @var \XF\Entity\Oembed */
       
$oEmbed = $this->em()->create('XF:Oembed');
       
$oEmbed->media_site_id = $mediaSiteId;
       
$oEmbed->media_id = $mediaId;
       
$oEmbed->is_processing = time();

        try
        {
           
$oEmbed->save();
        }
        catch (\
Exception $e)
        {
            return
null;
        }

       
$fetchResults = $this->fetchJsonData($mediaSiteId, $mediaId);
       
$this->finalizeFromFetchResults($oEmbed, $fetchResults);

        return
$oEmbed;
    }

    public function
refetchOembed(\XF\Entity\Oembed $oEmbed)
    {
       
$oEmbed->is_processing = time();
       
$oEmbed->save();

       
$fetchResults = $this->fetchJsonData($oEmbed->BbCodeMediaSite, $oEmbed->media_id);
       
$this->finalizeFromFetchResults($oEmbed, $fetchResults);

        return
$oEmbed;
    }

    public function
testOembedFetch($mediaSiteId, $mediaId)
    {
       
$results = $this->fetchJsonData($mediaSiteId, $mediaId);
        if (
$results['dataFile'])
        {
            @
unlink($results['dataFile']);
           
$results['dataFile'] = null;
        }

        return
$results;
    }

   
/**
     * @param \XF\Entity\BbCodeMediaSite|string $mediaSiteId Use the BbCodeMediaSite entity to avoid a query,
     *                                                       otherwise use media_site_id
     * @param string $mediaId
     *
     * @return array
     */
   
protected function fetchJsonData($mediaSiteId, $mediaId)
    {
       
$url = $this->oEmbedRepo->getOembedUrl($mediaSiteId, $mediaId);

        return
$this->fetchJsonDataFromUrl($url);
    }

    protected function
fetchJsonDataFromUrl($url)
    {
        if (!
preg_match('#^https?://#i', $url))
        {
            throw new \
InvalidArgumentException("URL must be http or https");
        }

       
$validOembed = false;
       
$title = null;
       
$error = null;
       
$streamFile = \XF\Util\File::getTempDir() . '/' . strtr(md5($url) . '-' . uniqid(), '/\\.', '---') . '.temp';

        try
        {
           
$options = [];
           
$limits = [
               
'time' => 5,
               
'bytes' => 1.5 * 1024 * 1024
           
];

           
$response = $this->app->http()->reader()->getUntrusted($url, $limits, $streamFile, $options, $error);
        }
        catch (\
Exception $e)
        {
           
$response = null;
           
$error = $e->getMessage();
        }

        if (
$response)
        {
           
$jsonText = $response->getBody()->getContents();

           
$response->getBody()->close();

            if (
$response->getStatusCode() == 200)
            {
                try
                {
                   
$json = json_decode($jsonText, true);

                    if (!empty(
$json['title']))
                    {
                       
$title = $json['title'];
                    }
                    else if (!empty(
$json['author_name']))
                    {
                       
$title = $json['author_name'];
                    }

                   
$validOembed = true;
                }
                catch (\
Exception $e)
                {
                   
$error = \XF::phraseDeferred('returned_data_is_not_json');
                }
            }
            else
            {
               
$error = \XF::phraseDeferred('received_unexpected_response_code_x_message_y', [
                   
'code' => $response->getStatusCode(),
                   
'message' => $response->getReasonPhrase()
                ]);
            }
        }

        if (!
$validOembed)
        {
            @
unlink($streamFile);
        }

        return [
           
'valid' => $validOembed,
           
'title' => \XF::cleanString($title),
           
'error' => $error,
           
'dataFile' => $validOembed ? $streamFile : null
       
];
    }

    protected function
finalizeFromFetchResults(\XF\Entity\Oembed $oEmbed, array $fetchResults, &$error = null)
    {
       
$oEmbed->is_processing = 0;

        if (
$fetchResults['valid'])
        {
           
$newJsonPath = $oEmbed->getAbstractedJsonPath();

            if (\
XF\Util\File::copyFileToAbstractedPath($fetchResults['dataFile'], $newJsonPath))
            {
               
$oEmbed->fetch_date = time();
               
$oEmbed->pruned = false;
               
$oEmbed->failed_date = 0;
               
$oEmbed->fail_count = 0;

                if (!empty(
$fetchResults['title']))
                {
                   
$oEmbed->title = $fetchResults['title'];
                }
            }
            else
            {
               
$oEmbed->pruned = true;
            }

            @
unlink($fetchResults['dataFile']);
        }
        else
        {
           
$oEmbed->failed_date = time();
           
$oEmbed->fail_count++;

           
$error = $fetchResults['error'];
        }

       
$oEmbed->save();
    }
}