Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Job/AbstractEmbedMetadataJob.php
<?php

namespace XF\Job;

use
XF\Mvc\Entity\Entity;

use function
is_array;

abstract class
AbstractEmbedMetadataJob extends AbstractJob
{
    protected
$defaultData = [
       
'steps' => 0,
       
'start' => 0,
       
'batch' => 1000,
       
'types' => []
    ];

    abstract protected function
getIdsToRebuild(array $types);
    abstract protected function
getRecordToRebuild($id);
    abstract protected function
getPreparerContext();
    abstract protected function
getMessageContent(Entity $record);
    abstract protected function
getActionDescription();

   
/**
     * @param $contentType
     *
     * Note: (bug #153298) as we currently only support attachments, it makes sense from a
     * performance perspective to query content_id from the xf_attachment table,
     * but if/when we start using additional types, we will need to query against the specific
     * content table (xf_post, xf_conversation message etc.) instead, as in XF <= 2.1.3
     *
     * @return array
     */
   
protected function getIdsBug153298Workaround($contentType)
    {
       
$db = $this->app->db();

        return
$db->fetchAllColumn($db->limit(
           
"
                SELECT DISTINCT content_id
                FROM xf_attachment
                WHERE content_type = ?
                AND content_id > ?
                ORDER BY content_id
            "
, $this->data['batch']
        ), [
$contentType, $this->data['start']]);
    }

    public function
run($maxRunTime)
    {
       
$startTime = microtime(true);

        if (!
is_array($this->data['types']))
        {
           
$this->data['types'] = [$this->data['types']];
        }

       
$this->data['steps']++;

       
$ids = $this->getIdsToRebuild($this->data['types']);
        if (!
$ids)
        {
            return
$this->complete();
        }

       
$done = 0;
       
$preparer = $this->getMessagePreparer($this->data['types']);

        foreach (
$ids AS $id)
        {
            if (
microtime(true) - $startTime >= $maxRunTime)
            {
                break;
            }

           
$this->data['start'] = $id;

           
$record = $this->getRecordToRebuild($id);
            if (!
$record)
            {
                continue;
            }

           
$preparer->setMessageEntity($record);

           
$embedMetadata = $this->getExistingMetadata($record);
            if (!
is_array($embedMetadata))
            {
               
$embedMetadata = [];
            }

           
$message = $this->getMessageContent($record);
           
$preparer->prepare($message, false);

            foreach (
$this->data['types'] AS $type)
            {
               
$method = 'rebuild' . \XF\Util\Php::camelCase($type);
                if (
method_exists($this, $method))
                {
                   
$this->{$method}($record, $preparer, $embedMetadata);
                }
            }

           
$this->saveMetadata($record, $embedMetadata);

           
$done++;
        }

       
$this->data['batch'] = $this->calculateOptimalBatch($this->data['batch'], $done, $startTime, $maxRunTime, 1000);

        return
$this->resume();
    }

    protected function
getExistingMetadata(Entity $record)
    {
        return
$record->embed_metadata;
    }

    protected function
saveMetadata(Entity $record, array $embedMetadata)
    {
       
$record->embed_metadata = $embedMetadata;
       
$record->save();
    }

   
/**
     * @param array $types
     *
     * @return \XF\Service\Message\Preparer
     */
   
protected function getMessagePreparer(array $types)
    {
       
/** @var \XF\Service\Message\Preparer $preparer */
       
$preparer = $this->app->service('XF:Message\Preparer', $this->getPreparerContext());
       
$preparer->disableAllFilters();

        return
$preparer;
    }

    public function
getStatusMessage()
    {
       
$description = $this->getActionDescription();
        return
sprintf('%s (%s)', $description, $this->data['start']);
    }

    public function
canCancel()
    {
        return
true;
    }

    public function
canTriggerByChoice()
    {
        return
true;
    }
}